之前看过一段时间c++,但是一直没有找到合适的项目进行熟悉,所以在跟着github的一个开源项目学习c++,地址为:github

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
38
39
40
41
42
43
44
45
46
/*
* 虚继承
* 概念:解决从不同途径继承来的同名数据成员在内存中有不同拷贝造成的数据不一致问题,将共同的基类设置为虚基类。
* 这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射
* 解决问题:
* 解决了二义性问题,也节省了内存,避免数据不一致问题
*
* 分析:
* 从程序中可以看到,C,D,E不同的继承类型为三种 public A,virtual A与virtual B,其中两次使用了virtual B
* 第二次的继承将会直接引用第一次的拷贝,所以我们会看到控制台对于C,D部分的输出为B-A-A其中第二次B被省略
* 按照继承的原则首先基类,生成C-D,然后成员为A,最后为E,所以顺序为:B-A-A-C-D-A-E
*
*/
# include <iostream>

using namespace std;

class A{
int a;
public:
A(){cout<<"Constructing A"<<endl;}
};
class B{
public:
B(){cout<<"Constructing B"<<endl;}
};
class C: public A,virtual public B{
public:
C(int j){cout<<"Constructing C"<<endl;}
};

class D:virtual public A,virtual public B{
public:
D(int j){cout<<"Constructing D"<<endl;}
};

class E: public C, public D{
public:
E(int m,int n):C(m),D(n){cout<<"Constructing E"<<endl;}
A a;
};

void main(){
E d(1,2);
system("pause");
}

在这里插入图片描述
虚继承的最终派生

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
38
39
40
41
42
#include <iostream>
using namespace std;

class A{
int a;
public:
A(int x){
a =x;
cout<<"virtual Base A .. "<<a<<endl;
}
};
class B:virtual public A{
public:
B(int x):A(x){
cout<<"virtual Base B .. "<<x<<endl;
}
};

class C:virtual public A{
int x;
public:
C(int x){
cout<<"Constructing C .. "<<x<<endl;
}
};

class ABC: public B, public C{
public:
ABC(int i,int j,int k):C(i),B(j),A(k){
/*
* 此处必须对A进行初始化,因为虚继承的初始化由最终派生类进行初始化
* 由于ABC是对A虚继承的最终派生类,所以需要在初始化时对A进行初始化
*/
cout<<"Constructing ABC .. "<<endl;
}
};

void main(){
ABC obj(1,2,3);
system("pause");
}

虚基类的最终派生将会对构造函数函数进行解析,包括(无参,无参和缺省函数),如果我们将A加入一个无参构造,将C省略将不会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A{
int a;
public:
A(){}
A(int x){
a =x;
cout<<"virtual Base A .. "<<a<<endl;
}
};
class C:virtual public A{
int x;
public:
C(int x){
cout<<"Constructing C .. "<<x<<endl;
}
};

在这里插入图片描述