gpt4 book ai didi

具有虚拟方法的 C++ 对象大小

转载 作者:太空狗 更新时间:2023-10-29 23:13:39 26 4
gpt4 key购买 nike

我对 virtual 的对象大小有一些疑问。

1)虚函数

class A {
public:
int a;
virtual void v();
}

A类的大小是8字节....一个整数(4字节)加一个虚拟指针(4字节)很清楚!

class B: public A{
public:
int b;
virtual void w();
}

B 类的大小是多少?我使用 sizeof B 进行了测试,它打印出来12

是不是说B类和A类都有虚函数也只有一个vptr?为什么只有一个vptr?

class A {
public:
int a;
virtual void v();
};

class B {
public:
int b;
virtual void w();
};

class C : public A, public B {
public:
int c;
virtual void x();
};

C的sizeof是20.......

似乎在这种情况下,布局中有两个 vptrs.....这是怎么发生的?我认为两个 vptr 一个用于 A 类,另一个用于 B 类....所以没有用于 C 类虚函数的 vptr?

我的问题是,继承的vptr数量有什么规定?

2)虚拟继承

    class A {
public:
int a;
virtual void v();
};

class B: virtual public A{ //virtual inheritance
public:
int b;
virtual void w();
};

class C : public A { //non-virtual inheritance
public:
int c;
virtual void x();
};

class D: public B, public C {
public:
int d;
virtual void y();
};

A 的大小是 8 个字节 -------------- 4(int a) + 4 (vptr) = 8

B的sizeof是16字节 -------------- 没有virtual应该是4 + 4 + 4 = 12。为什么这里还有4个字节? B类布局是怎样的?

C 的大小为 12 个字节。 -------------- 4 + 4 + 4 = 12。很明显!

D 的 sizeof 是 32 字节 -------------- 应该是 16(class B) + 12(class C) + 4(int d) = 32,对吗?

    class A {
public:
int a;
virtual void v();
};

class B: virtual public A{ //virtual inheritance here
public:
int b;
virtual void w();
};

class C : virtual public A { //virtual inheritance here
public:
int c;
virtual void x();
};

class D: public B, public C {
public:
int d;
virtual void y();
};

A 的大小为 8

B 的大小为 16

C 的大小为 16

sizeof D 是 28 是否意味着 28 = 16(class B) + 16(class C) - 8(class A) + 4(这是什么?)

我的问题是,为什么在应用虚拟继承时会有额外的空间?

在这种情况下,对象大小的基本规则是什么?

virtual应用于所有基类和部分基类有什么区别?

最佳答案

这是所有实现定义的。我正在使用 VC10 Beta2。帮助理解这些东西的关键(虚函数的实现),你需要知道 Visual Studio 编译器中的一个 secret 开关,/d1reportSingleClassLayoutXXX。我会在一秒钟内解决这个问题。

基本规则是,对于任何指向对象的指针,vtable 都需要位于偏移量 0 处。这意味着多个 vtable 用于多重继承。

这里有几个问题,我将从头开始:

Does it mean that only one vptr is there even both of class B and class A have virtual function? Why there is only one vptr?

这就是虚函数的工作方式,你希望基类和派生类共享同一个虚表指针(指向派生类中的实现。

It seems that in this case, two vptrs are in the layout.....How does this happen? I think the two vptrs one is for class A and another is for class B....so there is no vptr for the virtual function of class C?

这是 C 类的布局,由/d1reportSingleClassLayoutC 报告:

class C size(20):
+---
| +--- (base class A)
0 | | {vfptr}
4 | | a
| +---
| +--- (base class B)
8 | | {vfptr}
12 | | b
| +---
16 | c
+---

你是对的,有两个虚表,每个基类一个。这就是它在多重继承中的工作方式;如果将 C* 转换为 B*,指针值将调整 8 个字节。 vtable 仍然需要位于偏移量 0 处,虚函数调用才能正常工作。

A 类的上述布局中的 vtable 被视为 C 类的 vtable(当通过 C* 调用时)。

The sizeof B is 16 bytes -------------- Without virtual it should be 4 + 4 + 4 = 12. why there is another 4 bytes here? What's the layout of class B ?

这是本例中 B 类的布局:

class B size(20):
+---
0 | {vfptr}
4 | {vbptr}
8 | b
+---
+--- (virtual base A)
12 | {vfptr}
16 | a
+---

如您所见,有一个额外的指针来处理虚拟继承。虚拟继承很复杂。

The sizeof D is 32 bytes -------------- it should be 16(class B) + 12(class C) + 4(int d) = 32. Is that right?

不,36 字节。同样处理虚拟继承。本例中 D 的布局:

class D size(36):
+---
| +--- (base class B)
0 | | {vfptr}
4 | | {vbptr}
8 | | b
| +---
| +--- (base class C)
| | +--- (base class A)
12 | | | {vfptr}
16 | | | a
| | +---
20 | | c
| +---
24 | d
+---
+--- (virtual base A)
28 | {vfptr}
32 | a
+---

My question is , why there is an extra space when virtual inheritance is applied?

虚基类指针,比较复杂。基类在虚拟继承中被“组合”。不是将基类嵌入到类中,而是该类将在布局中具有指向基类对象的指针。如果您有两个使用虚拟继承的基类(“菱形”类层次结构),它们将都指向对象中的同一个虚拟基类,而不是拥有该基类的单独拷贝。

What's the underneath rule for the object size in this case?

要点;没有规则:编译器可以做任何它需要做的事情。

最后一个细节;制作我正在编译的所有这些类布局图:

cl test.cpp /d1reportSingleClassLayoutXXX

其中 XXX 是您要查看其布局的结构/类的子字符串匹配项。使用这个你可以自己探索各种继承方案的影响,以及为什么/在哪里添加填充等。

关于具有虚拟方法的 C++ 对象大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37782571/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com