用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++
參見 c++Primer 4th 第17.3.7節 特殊的初始化語義面試
一般每一個類只初始化本身的直接基類,可是在虛繼承的時候這個狀況發生了變化,可能致使虛基類被屢次初始化,這顯然不是咱們想要的。(例2: AA,AB都是類A的派生類,而後類C又繼承自AA和AB,若是按以前的方法會致使C裏面A被初始化兩次,也會存在兩份數據)函數
爲了解決重複初始化的問題,從具備虛基類的類繼承的類在初始化時進行了特殊處理,在虛派生中,由最低層次的派生類的構造函數初始化虛基類。在咱們上面的例1中就是由C的構造函數控制如何進行虛基類的初始化。spa
回到例1,由於B是Base的友元,因此B對象能夠正常建立,但因爲B使用了虛繼承,因此若是要建立C對象,那麼C類的構造函數就要負責虛基類(Base)的構造,可是Base的構造函數是私有的,C沒有訪問的權限(ps:友元關係不能被繼承的),因此例1中的C類在編譯時就會報錯。這樣B類就不能被繼承了。code
----------------------------------------------------對象
吐槽一下:面試中被問到這個問題,雖然答出了實現方法,可是原理沒回答上,因而回來以後查了一下繼承
你們都說這屬於「奇技淫巧」,哎,面試官就愛問這些 我也很無語啊
io