C++設計一個不能被繼承的類,為什么必須是虛繼承?原因分析

jopen 10年前發布 | 30K 次閱讀 C/C++開發 C/C++

使用友元、私有構造函數、虛繼承等方式可以使一個類不能被繼承,可是為什么必須是虛繼承?背后的原理又是什么?

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

#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; }</pre>

類Base的構造函數和析構函數因為是私有的,只有Base類的友元可以訪問,B類在繼承時將模板的參數設置為了B類,所以構造B類對象時們可以直接訪問父類(Base)的構造函數。

為什么必須是虛繼承(virtual)呢?

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

     通常每個類只初始化自己的直接基類,但是在虛繼承的時候這個情況發生了變化,可能導致虛基類被多次初始化,這顯然不是我們想要的。(例2: AA,AB都是類A的派生類,然后類C又繼承自AA和AB,如果按之前的方法會導致C里面A被初始化兩次,也會存在兩份數據)

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

為什么B類不能被繼承?

   回到例1,因為B是Base的友元,所以B對象可以正常創建,但由于B使用了虛繼承,所以如果要創建C對象,那么C類的構造函數就要負責虛基類(Base)的構造,但是Base的構造函數是私有的,C沒有訪問的權限(ps:友元關系不能被繼承的),所以例1中的C類在編譯時就會報錯。這樣B類就不能被繼承了。

----------------------------------------------------


來自:http://my.oschina.net/cuilili/blog/323696

 

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!