C++中多重继承对象的内存布局
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();
};
基于此article,classD
的一个对象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()
classD1
的对象呢?在classD1
中,成员f1
和f2
都声明为virtual
!
f1()
和 f2()
在 D
中也是 virtual。如果函数被声明为 virtual,它在继承的任何 class 中保持 virtual。
所以,class是D
和D1
内部几乎没有区别(但是,很明显,是不同的类型),但是它们都给出了[=16=的实现] 和 f2
,它们的 虚拟 tables 将不同,因为 D
的虚拟 table 将指向 D
的实现,D1
.
也是如此
vtable for D:
f1: D::f1
f2: D::f2
vtavle for D1:
f1: D1::f1
f2: D1::f2
virtual
在 D1
中的使用是多余的。
来自 C++11,§10.3¶2:
If a virtual member function vf
is declared in a class Base
and in a class Derived
, derived directly or indirectly from Base
, a member function vf
with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf
is declared, then Derived::vf
is also virtual (whether or not it is so declared) and it overrides111 Base::vf
.
111) A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override. The use of the virtual
specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (Clause 11) is not considered in determining overriding.
因此,D
和 D1
的内存布局(这似乎是问题所在)是相同的。显然,不同的类型会有不同的虚拟表。
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();
};
基于此article,classD
的一个对象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()
classD1
的对象呢?在classD1
中,成员f1
和f2
都声明为virtual
!
f1()
和 f2()
在 D
中也是 virtual。如果函数被声明为 virtual,它在继承的任何 class 中保持 virtual。
所以,class是D
和D1
内部几乎没有区别(但是,很明显,是不同的类型),但是它们都给出了[=16=的实现] 和 f2
,它们的 虚拟 tables 将不同,因为 D
的虚拟 table 将指向 D
的实现,D1
.
vtable for D:
f1: D::f1
f2: D::f2
vtavle for D1:
f1: D1::f1
f2: D1::f2
virtual
在 D1
中的使用是多余的。
来自 C++11,§10.3¶2:
If a virtual member function
vf
is declared in a classBase
and in a classDerived
, derived directly or indirectly fromBase
, a member functionvf
with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) asBase::vf
is declared, thenDerived::vf
is also virtual (whether or not it is so declared) and it overrides111Base::vf
.
111) A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override. The use of the
virtual
specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (Clause 11) is not considered in determining overriding.
因此,D
和 D1
的内存布局(这似乎是问题所在)是相同的。显然,不同的类型会有不同的虚拟表。