多重继承的虚拟函数表
virtual function table of multiple inheritance
示例代码如下:
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
有人能解释一下原因吗?
在子类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 A对象分配的最小大小是vtbl=4的sizeof指针由于A在实例数据方面是空的,所以空类的虚拟继承不会增加对象的大小
在类继承的上下文中,"虚拟"的意思是"在运行时确定"。有两个独立的东西可以是虚拟的,并且实现必须以某种方式实现:
-
虚拟函数,必须在运行时确定要调用的实际函数:
x.f()
—谁是f
?常见的实现涉及函数指针表。 -
虚拟继承,其中虚拟基础子对象直到运行时才知道。实现必须提供一种定位实际基础对象的机制:
x.a = 10
—其中是a
?这方面的常见实现涉及指针偏移量计算。
如果一个虚拟基类没有状态(这与"为空"类似,但不等价),那么第二个用例就变成了空的。由于不存在位置必须动态确定的数据成员,因此实现不需要为此生成任何信息,对象也不需要存储相关引用。
一个流行的C++ABI,安腾ABI,详细描述了虚拟性是如何实现的。还有一篇很受欢迎的文章解释了这个实现。
相关文章:
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 如何在C++中伪造虚拟可变参数函数模板?
- 类型擦除的std::function与虚拟函数调用的开销
- 重写虚拟函数和继承
- 是否可以使用函数指针调用虚拟析构函数?
- 在没有动态内存的世界中,我是否需要虚拟析构函数?
- 虚拟继承基构造函数消除
- "虚拟""覆盖"析构函数
- 类中的虚拟布尔函数参数不起作用
- 用纯虚拟函数兜圈子
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- 尝试在 QLabel 上绘画失败(无法在没有对象的情况下调用成员函数"虚拟无效 QLabel::p aintEvent(QPaintEvent*)")
- 声明析构函数虚拟就足够了吗?
- 视觉 C++当我们在基类中使函数成为纯虚拟时,那么在子类中再次使相同的函数虚拟的必要性是什么
- 重载函数(虚拟/非虚拟)