c++設計一個不能被繼承的類,爲何必須是虛繼承?緣由分析

用C++實現一個不能被繼承的類(例1)ios

#include <iostream>
using namespace std;

template <typename T>
class Base{
    friend T;
private:
    Base(){
        cout << "base" << endl;
    }
    ~Base(){}
};

class B:virtual public Base<B>{   //必定注意 必須是虛繼承
public:
    B(){
        cout << "B" << endl;
    }
};

class C:public B{
public:
    C(){}     //繼承時報錯,沒法經過編譯
};


int main(){
    B b;      //B類沒法被繼承
    //C c;
    return 0;
}

類Base的構造函數和析構函數由於是私有的,只有Base類的友元能夠訪問,B類在繼承時將模板的參數設置爲了B類,因此構造B類對象時們能夠直接訪問父類(Base)的構造函數。c++

爲何必須是虛繼承(virtual)呢?

參見 c++Primer 4th 第17.3.7節 特殊的初始化語義面試

     一般每一個類只初始化本身的直接基類,可是在虛繼承的時候這個狀況發生了變化,可能致使虛基類被屢次初始化,這顯然不是咱們想要的。(例2: AA,AB都是類A的派生類,而後類C又繼承自AA和AB,若是按以前的方法會致使C裏面A被初始化兩次,也會存在兩份數據)函數

    爲了解決重複初始化的問題,從具備虛基類的類繼承的類在初始化時進行了特殊處理,在虛派生中,由最低層次的派生類的構造函數初始化虛基類。在咱們上面的例1中就是由C的構造函數控制如何進行虛基類的初始化。spa

爲何B類不能被繼承?

   回到例1,由於B是Base的友元,因此B對象能夠正常建立,但因爲B使用了虛繼承,因此若是要建立C對象,那麼C類的構造函數就要負責虛基類(Base)的構造,可是Base的構造函數是私有的,C沒有訪問的權限(ps:友元關係不能被繼承的),因此例1中的C類在編譯時就會報錯。這樣B類就不能被繼承了。code

----------------------------------------------------對象

吐槽一下:面試中被問到這個問題,雖然答出了實現方法,可是原理沒回答上,因而回來以後查了一下繼承

你們都說這屬於「奇技淫巧」,哎,面試官就愛問這些 我也很無語啊
io

相關文章
相關標籤/搜索