码迷,mamicode.com
首页 > 其他好文 > 详细

钻石(菱形)继承和虚基类

时间:2019-02-03 16:46:04      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:构造顺序   16px   on()   span   iostream   作用域   相同   image   不同的   

钻石(菱形)继承

技术图片

如图,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;//两次赋值均对一个数据成员操作
}

技术图片

可以看到两个数据成员的地址相同。

运行结果

技术图片

析构顺序和构造顺序相反。

钻石(菱形)继承和虚基类

标签:构造顺序   16px   on()   span   iostream   作用域   相同   image   不同的   

原文地址:https://www.cnblogs.com/area-h-p/p/10350517.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!