钻石(菱形)继承和虚基类
Posted area-h-p
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了钻石(菱形)继承和虚基类相关的知识,希望对你有一定的参考价值。
钻石(菱形)继承
如图,B,C继承了A,D继承了B,C
在这种情况下,如果D类的对象通过B、C两个不同的作用域调用A的数据成员,将会产生两个
不同的A的数据成员值
如下(Grandfather对应A,a是其公有数据成员,Father1,Father2对应B、C,son对应D的对象,)
可以看到有两个不一样的a存在,说明在赋值过程中Father1,Father2分别调用Grandfather产生两个a
从其运行结果也可以看出来
如果son对象仅想产生一个数据成员a,则必须对Grandfather进行虚继承
//Test1.h #include<iostream> using namespace std; class Grandfather { public: int a; Grandfather(int _a):a(_a) { cout<<"Grandfather was built. "<<endl; } ~Grandfather(){cout<<"Grandfather was free. "<<endl;} }; class Father1 : public virtual Grandfather { public: int n; Father1(int _a) : n(_a),Grandfather(_a) { cout<<"Father1 was built. "<<endl; } ~Father1(){cout<<"Father1 was free. "<<endl;} }; class Father2 : virtual public Grandfather //virtual写在public前后都可以 { public: int n; Father2(int _a) : n(_a),Grandfather(_a) { cout<<"Father2 was built. "<<endl; } ~Father2(){cout<<"Father2 was free. "<<endl;} }; class Son : public Father1, public Father2 { public: Son(int _a):Father1(_a),Father2(_a),Grandfather(_a) { cout<<"Son was built. "<<endl; } ~Son(){cout<<"Son was free. "<<endl;} };
虚继承就是在继承符(public、protected、private)前或后加上virtual关键字,被虚继承的类也叫虚基类
在派生类对象的创建中,
首先是虚基类的构造函数并按他们声明顺序构造。
第二批是非虚基类的构造函数按他们声明的顺序调用
第三批是成员对象的构造函数
最后是派生类自己的构造函数。
#include"Test1.h" void main() { Son son(10); son.Father1::n = 1; son.Father2::n = 2;//由于在Father1,Father2内均存在公有数据n,在对其赋值时需要加上作用域 son.Father1::a = 5; son.Father2::a = 6;//两次赋值均对一个数据成员操作 }
可以看到两个数据成员的地址相同。
运行结果
析构顺序和构造顺序相反。
以上是关于钻石(菱形)继承和虚基类的主要内容,如果未能解决你的问题,请参考以下文章