1. 程式人生 > 其它 >c++ 虛繼承

c++ 虛繼承

技術標籤:C++

之前看過一段時間c++,但是一直沒有找到合適的專案進行熟悉,所以在跟著github的一個開源專案學習c++,地址為:github

/*
 * 虛繼承
 * 概念:解決從不同途徑繼承來的同名數據成員在記憶體中有不同拷貝造成的資料不一致問題,將共同的基類設定為虛基類。
 * 這時從不同的路徑繼承過來的同名數據成員在記憶體中就只有一個拷貝,同一個函式名也只有一個對映
 * 解決問題:
 * 解決了二義性問題,也節省了記憶體,避免資料不一致問題
 *
 * 分析:
 * 從程式中可以看到,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");
}

在這裡插入圖片描述
虛繼承的最終派生

#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省略將不會報錯。

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;
    }
};

在這裡插入圖片描述