C++ C++;虚拟方法的对象大小
我有一些关于虚拟对象大小的问题 1)虚拟功能C++ C++;虚拟方法的对象大小,c++,virtual-functions,objectsize,C++,Virtual Functions,Objectsize,我有一些关于虚拟对象大小的问题 1)虚拟功能 class A { public: int a; virtual void v(); } 类的大小是8字节…一个整数(4字节)加上一个虚拟指针(4字节) 很清楚 class B: public A{ public: int b; virtual void w(); } B类的尺寸是多少?我用sizeof B测试过,它可以打印 十二, 这是否意味着只有一个vptr,即使
class A {
public:
int a;
virtual void v();
}
类的大小是8字节…一个整数(4字节)加上一个虚拟指针(4字节)
很清楚
class B: public A{
public:
int b;
virtual void w();
}
B类的尺寸是多少?我用sizeof B测试过,它可以打印
十二,
这是否意味着只有一个vptr,即使B类和A类都有虚拟功能?为什么只有一个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的尺寸是20
在这种情况下,布局中似乎有两个VPTR……这是如何发生的?我认为这两个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(inta)+4(vptr)=8
B的大小是16个字节------------如果没有虚拟值,它应该是4+4+4=12。为什么这里还有4个字节?B班的布局是什么
C的大小是12个字节。-------------4 + 4 + 4 = 12. 很清楚
class B: public A{
public:
int b;
virtual void w();
}
D的大小是32字节------------它应该是16(B类)+12(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
D的大小是28,这是否意味着28=16(B类)+16(C类)-8(A类)+4(这是什么?)
我的问题是,为什么应用虚拟继承时会有额外的空间
在这种情况下,对象大小的基本规则是什么
当virtual应用于所有基类和部分基类时有什么区别呢?我不确定,但我认为这是因为指向的指针,所有这些都是您意识到的完全由实现定义的。你不能指望这些。没有“规则” 在继承示例中,下面是类A和B的虚拟表的外观:
class A
+-----------------+
| pointer to A::v |
+-----------------+
class B
+-----------------+
| pointer to A::v |
+-----------------+
| pointer to B::w |
+-----------------+
如您所见,如果您有一个指向类B的虚拟表的指针,那么它作为类a的虚拟表也是完全有效的
在您的C类示例中,如果您仔细想想,就无法生成一个虚拟表,该虚拟表作为C类、a类和B类的表都是有效的。一个虚拟表对A类和C类有效(很可能),另一个对A类和B类有效。这都是实现定义的。我用的是VC10β2。帮助理解这些内容(虚拟函数的实现)的关键是,您需要了解Visual Studio编译器中的一个秘密开关,/d1reportSingleClassLayoutXXX。我马上就讲 基本规则是,对于指向对象的任何指针,vtable都需要位于偏移量0处。这意味着多重继承有多个vtable 这里有几个问题,我将从顶部开始: 这是否意味着只有一个vptr,即使B类和A类都有虚拟功能?为什么只有一个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();
};
这就是虚拟函数的工作方式,您希望基类和派生类共享同一个vtable指针(指向派生类中的实现)
似乎在这种情况下,布局中有两个vptr…这是怎么发生的?我认为两个vptr一个用于A类,另一个用于B类…因此C类的虚拟功能没有vptr
这是C类的布局,由/D1ReportSingleClassLayoutUTC报告:
class C size(20):
+---
| +--- (base class A)
0 | | {vfptr}
4 | | a
| +---
| +--- (base class B)
8 | | {vfptr}
12 | | b
| +---
16 | c
+---
您是正确的,有两个vtable,每个基类一个。这是它在多重继承中的工作方式;如果将C*强制转换为B*,指针值将调整8个字节。vtable仍然需要位于偏移量0处,虚拟函数调用才能工作
上述A类布局中的vtable被视为C类的vtable(通过C*调用时)
B的大小是16个字节------------如果没有虚拟,它应该是4+4+4=12。为什么这里还有4个字节?B类的布局是什么
这是本例中B类的布局:
class B size(20):
+---
0 | {vfptr}
4 | {vbptr}
8 | b
+---
+--- (virtual base A)
12 | {vfptr}
16 | a
+---
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
+---
正如您所看到的,有一个额外的指针来处理虚拟继承。虚拟继承非常复杂
D的大小是32字节------------------它应该是16(B类)+12(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();
};
不,36字节。虚拟继承的处理方法相同。本例中D的布局:
class B size(20):
+---
0 | {vfptr}
4 | {vbptr}
8 | b
+---
+--- (virtual base A)
12 | {vfptr}
16 | a
+---
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
+---
我的问题是,为什么应用虚拟继承时会有额外的空间
虚拟基类指针,很复杂。基类在虚拟继承中是“组合”的。类中没有嵌入基类,而是有一个指向布局中基类对象的指针。如果有两个使用虚拟继承的基类(“菱形”类层次结构),它们都将指向对象中的同一虚拟基类,而不是该基类的单独副本
在这种情况下,对象大小的基本规则是什么
重要的一点;没有规则:编译器可以做它需要做的任何事情
最后一个细节;为了制作所有这些类布局图,我正在使用:
cl test.cpp /d1reportSingleClassLayoutXXX
其中XXX是您希望查看其布局的结构/类的子字符串匹配。使用它,您可以自己探索各种继承方案的影响,以及添加填充的原因/位置等。考虑它的一个好方法是了解处理强制转换必须做些什么。我将通过显示您描述的类的对象的内存布局 代码示例#2 内存布局如下所示: vptr | A::a | B::b vptr | A::A | B::B 将指向B的指针向上投射到类型a将产生相同的地址,使用相同的vptr。这就是为什么这里不需要额外的vptr 代码示例#3 vptr | A::A | vptr | B::B | C::C 正如你所看到的,这里有两个vptr,正如你所猜测的。为什么?因为它是tr