编译器构造 - C++中多个继承对象的内存布局
compiler construction - memory layout of a multiple-inherited object in C++
class B1 {
virtual void f1();
int int_in_b1;
};
class B2 {
virtual void f2();
int int_in_b2;
};
class D: B1, B2 {
int int_in_d;
void f1();
void f2();
};
class D1: B1, B2 {
int int_in_d;
virtual void f1();
virtual void f2();
};
根据本文,类D
的对象d
的内存布局如下所示:
d:
+0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
+8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
virtual method table of D (for B1):
+0: D::f1() // B1::f1() is overridden by D::f1()
virtual method table of D (for B2):
+0: D::f2() // B2::f2() is overridden by D::f2()
类D1
的对象呢?在类D1
中,成员f1
和f2
都被声明为virtual
!
virtual
的使用在D1
中是多余的。
从 C++11 §10.3¶2 开始:
如果一个虚成员函数
vf
是在类Base
和类Derived
中声明的,直接或间接派生自Base
,则成员函数vf
声明的名称、参数类型列表(8.3.5)、cv限定符和ref限定符(或缺少相同Base::vf
),则Derived::vf
也是虚的(无论它是否如此声明),并且它覆盖了111Base::vf
。
111)具有相同名称但不同参数列表(条款13)的函数作为虚函数不一定是虚函数,也不会覆盖。在重写函数的声明中使用
virtual
说明符是合法的,但冗余(具有空语义)。在确定覆盖时不考虑访问控制(第 11 条)。
因此,内存布局(这似乎是问题所在)对于D
和D1
是相同的。显然,不同的类型将具有不同的虚拟表。
f1()
和f2()
在D
中也是虚拟的。如果函数被声明为 virtual,则它在继承的任何类中都保持 virtual 状态。
因此,类 D
和 D1
内部几乎没有区别(但显然是不同的类型),但它们都给出了 f1
和 f2
的实现,它们的虚拟表也会有所不同,因为D
的虚拟表将指向D
的实现,D1
也是如此。
vtable for D:
f1: D::f1
f2: D::f2
vtavle for D1:
f1: D1::f1
f2: D1::f2
相关文章:
- 如何创建从同一类继承的不同对象的向量
- 如何在QT Creator上将QWidget声明为继承类的对象
- 如果'C'公开继承'B',B 私下继承'A',为什么我不能在"C"中创建"A"的对象?
- 私有字段对象与私有继承?
- 为什么我不能在主函数之外定义一个类的对象(它继承了另一个类)?
- C++:返回一个基于范围 for 循环迭代器,其中包含继承对象
- 使用智能指针附加的继承对象的深层复制
- 如何继承返回对当前对象的引用的方法?
- C++具有空派生类对象的继承大小
- 防止在按值传递对象(继承)时进行切片
- 具有多个继承共享一个资源的对象 - 寻找良好的设计模式
- 对象成员变量还是继承
- 继承 - 查找类的对象的大小
- 成员子对象继承存储持续时间是否有任何非直观的副作用
- 访问从 QObject 继承的对象继承的类的Q_Properties
- c++如何返回当前类类型的对象(继承)
- 在对象继承中构造对象后设置稍后的值
- c++ -从其他对象继承std::元组,并为其添加虚函数
- 我有一个基对象和派生类对象的向量,但我无法访问存储在向量中的派生对象继承的数据成员
- 从基础对象继承接口是一种好的做法吗