C++虚继承
发表于:2024-12-14 | 分类: C++
字数统计: 585 | 阅读时长: 2分钟 | 阅读量:

虚继承

菱形继承题

1
2
3
4
5
  A
/ \
B C
\ /
D
  • 重复拷贝:A的属性和方法被B和C拷贝两份给D
  • 二义性:既然有两份A的属性和方法,我怎么区分
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
public:
int x;
};
class B : public A {};
class C : public A {};
class D : public B, public C {};

int main() {
D obj;
obj.x = 10; // 错误:编译器会不知道 `x` 是来自 `B` 还是来自 `C`!
return 0;
}

虚继承

  • C++ 提供了虚继承(virtual inheritance)机制,专门用来解决菱形问题。
  • 通过虚继承,可以确保从多个路径继承同一个基类时,只保留一份基类的成员
1
2
3
4
5
6
7
8
class A {
public:
int x;
};

class B : virtual public A {};
class C : virtual public A {};
class D : public B, public C {};

案例

  • 普通继承:A是间接基类,D是不能调用它的构造的,只能调用它的直接基类构造
  • 虚继承:A是B和C的直接基类,是D的间接基类,A的初始化由D决定,B和C对A的初始化无效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;

class A {
public:
int x;
A() : x(0) { cout << "A constructor" << endl; }
};

class B : virtual public A {
public:
B() { cout << "B constructor" << endl; }
};

class C : virtual public A {
public:
C() { cout << "C constructor" << endl; }
};

class D : public B, public C {
public:
D() { cout << "D constructor" << endl; }
};

int main() {
D obj; // 只会执行一次A的构造,BC对A的构造不生效
obj.x = 10; // 只有一份 A::x,不会有二义性
cout << "x = " << obj.x << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
using namespace std;

class A
{
public:
int x;
A(int a) : x(a) { cout << "A constructor" << endl; }
};

class B : virtual public A
{
public:
// 显式调用
B() : A(0) { cout << "B constructor" << endl; }
};

class C : virtual public A
{
public:
// 显式调用
C() : A(1) { cout << "C constructor" << endl; }
};

class D : public B, public C
{
public:
// 显式调用
D() : A(10), B(), C() { cout << "D constructor" << endl; }
};

int main()
{
D obj; // 只会执行一次A的构造,BC对A的构造不生效
cout << "x = " << obj.x << endl; // 10,是D初始化A的值,BC无效
return 0;
}
上一篇:
C++多态和虚函数
下一篇:
C++多继承