3

可能重复:
对象大小与虚拟

虚拟继承会改变派生类的大小吗?我执行了以下代码,其中我有两个派生类,一个是虚拟继承的,另一个是非虚​​拟继承的:

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


class non_vir_der: public A{
 public:
int c;
  virtual void aa();
};


class vir_der: public virtual A{
public:
int d;
virtual void bb();
};

int main()
{
cout<<sizeof(non_vir_der)<<"\n";
cout<<sizeof(vir_der)<<"\n";
return 0;
}

输出:

12(imo:4(int a)+ 4(int c)+ 4(vir ptr))

16(额外 4 个?)

为了再次检查我是否遗漏了什么,我尝试了所需的最少代码,方法是删除类中的所有整数,输出为:

4

4

第二个输出表明两个派生类的大小相同。为什么第一次运行时vir_der的大小是16,为什么不是12?

4

2 回答 2

6

这种行为完全是特定于实现的,并且不能保证会发生什么。也就是说,大多数编译器通过放置基类的单个副本来实现虚拟继承,然后让派生类的每个实例在其类体内存储一个指向该唯一实例的指针。这样,如果您将对象转换为它的虚拟基,编译器可以发出代码来找出该对象的位置。正如您所观察到的,在 32 位系统上,这意味着虚拟继承可能会将对象的大小增加四个字节。

那么,如果没有数据成员,为什么没有区别呢?我不确定,但我猜这是因为编译器足够聪明,可以意识到如果您有一个没有数据成员的虚拟基类,您实际上不需要访问其中包含的任何内容。因此,可以通过消除指向虚拟基的额外指针来优化对象,因为永远无法访问它。不过,我可能错了。

希望这可以帮助!

于 2012-06-15T00:22:59.410 回答
0

基本上,当你声明一个函数或类 virtual 时,编译器会实例化一个 virtual

UPCAST​​ING 时需要的指针。实际上,创建了一个虚拟指针表

所有虚拟实例都与它们的实际地址一起存储。因此,当你继承

第二种情况下的虚拟类,创建了一个额外的 *vptr。

现在是第二种情况,为什么在这两种情况下都是 4 ......这完全是编译器特定的。

根据简单的逻辑,第一种情况下应该是 1,第二种情况下应该是 4。

谢谢

于 2012-06-15T04:16:03.093 回答