用C++實現一個不能被繼承的類


一道筆試題的思考:

記得,找工作時,遇到了這樣的一道筆試題。

記不清是那個公司的筆試題,反正覺得自己當時還真費了一點功夫的,但是也就搞定了一部分,結果還是被另一部分給鄙視啦!

現在靜下來分析實現如下:

題目:用C++設計一個不能被繼承的類

不能被繼承?不能被繼承?不能被繼承?按照繼承的理論知識分析,我們只要把類的構造函數設置為私有的,即可解決問題。

因為那樣的話,子類就沒有辦法訪問基類的構造函數,從而就阻止了進行子類構造對象的任務實現,也就達到了不可繼承的目的。

但是,假設那樣,這個類我們在其它地方怎么使用呢?那這樣子給我們的利用也造成了一定的障礙。

好了。你是不是也想到了,定義靜態方法,在方法內部實現一個對象,然后返回它的指針。

Ok?那怎么釋放掉呢?再照樣設計一個釋放內存函數,問題就會迎刃而解。

OK。按照這個邏輯分析。示例代碼如下:

 1 #include<iostream>
 2 using  namespace std;
 3 
 4 class A
 5 {
 6 public:
 7     static A * Construct(int  n)
 8     {
 9         A *pa = new A;
10         pa->num = n;
11         cout << "num  is:" << pa->num << endl;
12         return pa;
13     }
14     static void Destruct(A * pIntance)
15     {
16         delete  pIntance;
17         pIntance = NULL;
18     }
19 
20 private:
21     A(){}
22     ~A(){}
23 
24 public:
25     int num;
26 };
27 
28 void  main()
29 {
30     A *f = A::Construct(9);
31     cout << f->num << endl;
32     A::Destruct(f);
33 }

好了,這個類就這樣子。按照理論分析,我們的實踐結果也是完全成立的。

但是,這個題,它比較有挑戰性,什么意思呢?難道你沒有發現,咱們這水平也就僅僅有面試資格,還不可以破格錄用的。

怎么啦?你可能會反問我。難道你真的沒有看明白?確定沒有看明白?如果是真的話,那我就告訴你吧!

咱們的類不可以實現在棧上創建對象。也就是說,僅僅只可以在堆上構建任何的一個對象,而在棧上就無能為力了。

私有的構造函數極大的局限性就這樣一覽無余了。(其實,上面類設計即是一種只可以創建堆對象,不可以創建棧對象的情況。)

好吧!我們修改它,也就是所謂的為它打“補丁吧”,請看示例代碼:

 1 #include<iostream>
 2 using namespace std;
 3 
 4 template <typename T> 
 5 class Base
 6 {
 7     friend T;
 8 private:
 9     Base() {}
10     ~Base() {}
11 };
12 
13 class Finalclass : virtual public Base<Finalclass>
14 {                
15 public:
16     Finalclass() {}
17     ~Finalclass() {}
18 };
19 
20 class TestClass : public Finalclass
21 {
22 };
23 
24 void  main()
25 {
26     Finalclass* p = new Finalclass;  // 堆上對象
27     Finalclass fs;               // 棧上對象
28 //  TestClass tc;  // 基類構造函數私有,不可以被繼承。因此不可以創建棧上對象。
29 
30     system("pause");
31 }

OK 代碼碼完。現在分析Finalclass類:

繼承於Base類,Base為虛基類,因為它是Base的友元,所以,它可以訪問基類的私有構造函數,以及析構函數。編譯運行時是正確的。

也就是說,可以創建堆上的對象,並且可以構建棧上的對象。

可否繼承?假如它作為一個基類被另一個類繼承,編譯時是完全可以通過的。這一點沒有什么疑問。

但問題就在需要構建對象時:

當派生類TestClass在構造對象時,因為是虛繼承,所以派生類TestClass的構造函數會直接去調用Base基類的構造函數,而Base的構造函數是私有的。編譯錯誤!

這就是一個真正不能被繼承的類。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM