您的位置:首页 > 编程语言 > C语言/C++

c++类多重继承初始化顺序

2013-08-08 13:44 330 查看
c++类多重继承时,初始化顺序是一个基础的问题,笔者每次清楚了以后,过段时间有点含糊了,有些基础的问题,在实际开发中,用到的频率少,今天做一个总结跟大家一起分享。

这里先讨论一般的基类继承时的初始化行为,然后再讨论虚基类的情况。

例子1:

#include<iostream>

using namespace std;

class CBase

{

    private:

         int a;

    public:

         CBase(int va):a(va)

        {

            cout<<"CBase:"<<endl<<this->a<<endl;

        }

};

class A:public CBase

{

    private:

        int t;

    public:

        A(int vt,int ut):t(vt),CBase(ut)

        {

            cout<<"A:"<<endl<<this->t<<endl;    

        }

    

};

class B:public CBase

{

    private:

        int t;

    public:

        B(int vt,int ut):t(vt),CBase(ut)

        {

            cout<<"B:"<<endl<<this->t<<endl;

        }

};

class C:public B,public A

{

    private:

        int t;

    public:

        //C(int vt,int ut,int kt):A(vt,ut),B(vt,ut),CBase(kt)

        C(int vt,int ut,int kt):A(vt,ut),B(vt,ut),t(kt)

        {

            cout<<"C:"<<endl<<this->t<<endl;

        }

};

int main()

{

    C cc(1,2,3);

    return 0;

}

输出结果:



注意类C的继承顺序和构造函数初始化顺序,蓝色和红色字体,刚好是相反的,从输出结果可以看到,是一继承顺序为依据的,先调用B的构造函数,B的构造函数执行前又先调用CBase基类的构造函数,然后是类成员的初始化,最后是类构造函数体部分的执行,以此类推,总结下顺序:

1、根据继承顺序,父类构造函数,回退到基类先开始

2、类成员初始化

3、构造函数体部分初始化

另外有一点需要注意的是,C类(红色字体部分)如果用注释掉的语句来初始化,会报错的,这里就引入了虚基类的问题,类似这种CBase类作为A和B类的共同基类,而C类又继承A和B,C++类在继承的时候,存在一个膨胀的问题的,所以才会有一种设计模式“尽量用聚合或者组合的方式”实现,而不是首先考虑继承,继承的层级过深,在性能和资源的占用上是需要衡量的,虚基类正好是可以解决这个问题的,今天重点讨论的是,虚基类继承的初始化行为,看下面的例子2:

#include<iostream>

using namespace std;

class CBase

{

    private:

         int a;

    

    public:

         CBase(int va):a(va)

        {

            cout<<"CBase:"<<endl<<this->a<<endl;

        }

        

};

class A:virtual public CBase

{

    private:

        int t;

    public:

        A(int vt,int ut):t(vt),CBase(ut)

        {

            cout<<"A:"<<endl<<this->t<<endl;    

        }

    

};

class B:virtual public CBase

{

    private:

        int t;

    public:

        B(int vt,int ut):t(vt),CBase(ut)

        {

            cout<<"B:"<<endl<<this->t<<endl;

        }

};

class C:public B,public A

{

    private:

        int t;

    public:

        C(int vt,int ut,int kt):A(vt,ut),B(vt,ut),CBase(kt),t(kt)

        //C(int vt,int ut,int kt):A(vt,ut),B(vt,ut),t(kt)

        {

            cout<<"C:"<<endl<<this->t<<endl;

        }

};

int main()

{

    C cc(1,2,3);

    return 0;    

}

输出结果:



对比例子1的结果,是有比较大的区别的,虚基类的构造要最先执行并且执行一次,当再次调用A类和B类的构造函数时,CBase类的构造函数不再调用执行,这也正说明了,虚基类解决了这种冗余继承时候的“膨胀”问题。

除了这个顺序不同外,其余的顺序还是一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 继承 虚基类