多重继承
多重继承
- 一个派生类具有多个基类
- 优点,代码复用
class A : public C, public B
{
};
抽象类
具有纯虚函数的类
虚基类
- virtual 可以修饰成员函数,叫做虚函数
- virtual修饰继承方式,是虚继承。被虚继承的类,叫做虚基类
派生类虚继承后的内存布局
#include <iostream>
class Base
{
public:
Base(int a):ma(a){
}
virtual void show() {
}
private:
int ma;
};
class Drived : virtual public Base {
public:
Drived(int data):Base(data),mb(data){
}
void show() {
}
private:
int mb;
};
int main()
{
Drived d(10);
}
下图为上述代码类 class Drived的内存分布。
class Drived size(40):
+---
0 | {
vbptr}
8 | mb
| <alignment member> (size=4)
| <alignment member> (size=4)
+---
20 | (vtordisp for vbase Base)
+--- (virtual base Base)
24 | {
vfptr}
32 | ma
| <alignment member> (size=4)
+---
由于Base为虚基类,所以当Drived虚继承Base的时候,class Drived内存就会如上所示。从Base继承而来的部分,被放在Drived内存末尾,并且在内存首部使用了一个vbptr,该指针指向存放于末尾的Base的部分。
菱形继承
解决方式:虚继承
实例
class A {
public:
A(int data) : a(data) {
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int a;
};
class B : virtual public A {
public:
B(int data) : A(data)
, b(data) {
cout << "B()" << endl;
}
~B()
{
cout << "~B()" << endl;
}
private:
int b;
};
class C : virtual public A {
public:
C(int data) : A(data)
,c(data) {
cout << "C()" << endl;
}
~C()
{
cout << "~C()" << endl;
}
private:
int c;
};
class D :public B, public C{
public:
D(int data) : A(data)
,B(data)
,C(data)
,d(data) {
cout << "D()" << endl;
}
~D() {
cout << "~D()" << endl;
}
private:
int d;
};
int main()
{
D d(10);
}
class D的内存分布
class D size(48):
+---
0 | +--- (base class B)
0 | | {vbptr}
8 | | b
| | <alignment member> (size=4)
| | <alignment member> (size=4)
| +---
16 | +--- (base class C)
16 | | {vbptr}
24 | | c
| | <alignment member> (size=4)
| | <alignment member> (size=4)
| +---
32 | d
| <alignment member> (size=4)
| <alignment member> (size=4)
+---
+--- (virtual base A)
40 | a
+---
D::$vbtable@B@:
0 | 0
1 | 40 (Dd(B+0)A)
D::$vbtable@C@:
0 | 0
1 | 24 (Dd(C+0)A)
- 使用虚继承,虚基类A部分的变量被放置到类D的末尾
- B、C里面的虚基类部分被替换成vbptr指向A部分
- 对A进行构造的时候需要在D内部单独构造,而不是经过B、C进行构造