示例代码如下:
class A
{
public:
int k;
virtual int f();
};
class B:public virtual A
{
public:
virtual int a();
};
int main()
{
cout<<sizeof(A)<<sizeof(B);
}
打印
8 12
似乎class B
有自己的新虚函数表。
如果class A
更改为:
class A
{
public:
virtual int f();
};
打印
4 4
有人可以解释原因吗?
答案 0 :(得分:1)
在子类B中,B是A的虚拟子类。因此,B在子对象A上有一个单独的vtbl指针(4个字节)。 因此,
sizeof(B object)
= sizeof(A object) + sizeof (vtbl pointer of B)
= sizeof(int) + sizeof (vtbl pointer of A) + sizeof (vtbl pointer of B)
= 4 + 4 + 4
= 12
而且,
sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 8
如果B是A的正常子类,
sizeof(B object)
= sizeof(A object)
= sizeof(int) + sizeof (vtbl pointer of A)
= 4 + 4
= 12
对于空类A,为sizeof分配的最小大小对象是vtbl = 4的sizeof指针 由于A在实例数据方面是空的,因此空类的虚拟继承不会增加对象的大小
答案 1 :(得分:0)
在类继承的上下文中,&#34;虚拟&#34;意味着&#34;在运行时确定&#34;。有两个单独的东西可以是虚拟的,并且实现必须以某种方式实现:
虚拟函数,必须在运行时确定要调用的实际函数:x.f()
- 谁是f
?常见的实现涉及函数指针表。
虚拟继承,其中直到运行时才知道虚拟基础子对象。实现必须提供一种机制来定位实际的基础对象:x.a = 10
- 其中是a
?这种常见的实现涉及指针偏移计算。
如果虚拟基类没有状态(这是相似的,但不等效,对于&#34;为空&#34;),则第二个用例变为空。由于没有数据成员的位置必须动态确定,因此实现不需要生成任何信息来执行此操作,对象也不需要存储相关的引用。
一个流行的C ++ ABI,Itanium ABI,详细描述了how virtuality is implemented。还有this popular article解释了这种实现。