C++多态学习(二)菱形继承
简介
在前一篇笔记C++多态学习(一)单继承与多重继承中讨论了单继承和多重继承,本文将针对菱形继承进行讨论
菱形继承
class Base{
public:
Base()
{
printf("Base的this指针是:%p!\n", this);
}
virtual void func() { cout << "Base::func" << endl; }
virtual void func1() { cout << "Base::func1" << endl; }
virtual void func2() { cout << "Base::func2" << endl; }
int b; //4字节
};
class Base1 : public Base {
public:
Base1()
{
printf("Base1的this指针是:%p!\n", this);
}
//虚表指针8字节
void func() override { cout << "Base1::func" << endl; }
void func1() override { cout << "Base1::func1" << endl; }
virtual void func3() { cout << "Base1::func3" << endl; }
int b1; //4字节
};
class Base2 : public Base {
public:
Base2()
{
printf("Base2的this指针是:%p!\n", this);
}
void func() override { cout << "Base2::func" << endl; }
void func2() override { cout << "Base2::func2" << endl; }
virtual void func4() { cout << "Base2::func4" << endl; }
int b2;
};
class Derived : public Base1, public Base2 {
public:
Derived()
{
printf("Derive的this指针是:%p!\n", this);
}
void func() override { cout << "Derived::func" << endl; }
void func4() override { cout << "Derived::func4" << endl; }
void func3() override { cout << "Derived::func3" << endl; }
virtual void func5() { cout << "Derived::func5" << endl; }
int d;
};
内存布局
基类冗余
我们知道Derived
继承自Base1
和Base2
,而Base1
和Base2
又继承自Base
。这意味着Derived
的内存布局中会有两份Base
的拷贝。这会引起数据的不一致性和资源的浪费。
二义性
Derived obj;
obj.b = 1; //Derived::b不明确
Base* p = &obj; //基类Base不明确
对于obj.b
,编译器无法确定在通过Dervide
访问Base
的成员b
时应该选择哪条路径。
对于Base* p = &obj
,编译器无法确定p
应该指向通过Derived1
继承的Base
还是通过Derived2
继承的Base
。
小结
本文简单讨论了菱形继承的内存布局以及其可能导致的问题。针对上述问题,可以采用虚继承解决,虚继承将在下一篇笔记中讨论。
参考文章
1.VTable Notes on Multiple Inheritance in GCC C++ Compiler v4.0.1