我理解钻石继承树中虚拟继承的效果,但不理解非钻石继承树中的副作用(如果有)。
如果你有
class A;
class B: public virtual A;
这两个类的行为或内存布局(如果有),即构造函数调用的顺序等有什么不同。
假设class A
有数据成员。
请提供您的答案的官方文档
答案 0 :(得分:2)
虚拟继承的一个影响是static_cast
的向下转换不起作用。如果您想从虚拟基础向下转发,则必须改为使用dynamic_cast
。
A* pa = new B;
B* pb1 = static_cast<B*>(pa); // doesn't work: compilation error
B* pb2 = dynamic_cast<B*>(pa); // works
引自标准(5.2.9):
类型为“指向cv1 B的指针”的prvalue,其中B是类类型,可以转换为类型为“指向cv2 D的指针”的prvalue ...如果... B 既不是D的虚基类,也不是D的虚基类的基类。
答案 1 :(得分:0)
关于内存布局,一些编译器可能会将虚拟基础数据成员放在子类的数据成员之后(参见Multiple Inheritance Considered Useful):
class A {
public:
int a;
};
class B : public virtual A {
public:
int b;
};
int main() {
B b;
std::cout << "&b.a < &b.b = " << (&(b.a) < &(b.b)) << std::endl; // &b.a < &b.b = = 0
return 0;
}
另一方面,非虚拟基地的数据成员通常在之前在孩子的数据成员之前放置:
class A {
public:
int a;
};
class B : public virtual A {
public:
int b;
};
int main() {
B b;
std::cout << "&b.a < &b.b = " << (&(b.a) < &(b.b)) << std::endl; // &b.a < &b.b = 1
return 0;
}