面試題:寫一個不能被繼承的類,且能正常使用


實驗室同學今天面試,上來被問的第一個題就是”寫一個不能被繼承的類“

這個問題分享出來的時候,我驚呆了,因為腦子沒一點思路(這是什么鬼東西,項目里從來沒有用過,課堂上也沒聽過,在博客、問答區也沒遇見過)。C++里沒有相關的語法定義,也沒有特定的設計。冷靜判斷,覺得這應該就是設計模式一類的東西(這方面確實很欠缺)。不扯了,經過查閱資料,這題是Adobe 07年的面試題,是我太年輕~ 原題是:”寫一個不能被繼承的類,且能正常使用“,難度更大,考查了兩個知識點。

首先,不能被繼承的類,也就是它的子類繼承它后不能正常的實例化。其實,如果能考慮到這里,就很簡單了:子類需要實例化父類,將父類的構造函數設為private,子類就無法實例化了。再進一步,子類的析構函數需要調用父類的析構函數,所以將父類的析構函數設為private也能解決我們的問題。

 

問題的后半句將難度提升了兩個數量級:且能正常使用。如果將父類的構造函數設為private,它自己就無法正常,它自己的對象沒法正常的聲明、實例化。將構造函數設為了private非常的像單例模式,促使我們想通過friend函數解決無法實例化的問題(當然,如果析構函數是private就是無法釋放,它們同樣的原理,下文不再復述)。

哦,不不,停住,仔細看題目需求,這里要求正常的使用該類,而不是依靠額外的函數途徑去申請一個實例

這確實是一個難題~如果沒有看過答案,我肯定想不出來。我記得計算機世界有一句名言”一切難題都可以通過增加一個中間層去解決“

 

要正常的使用該類,它的構造函數和析構函數必然是public訪問權限。我們為它增加一個虛繼承的父類,它是父類的friend(友元),父類的構造函數是private。

直接上代碼:

 

 

class A;

class final
{
    friend class A;//class關鍵字不可省略,否則在g++中不能編譯通過
    final()
    {}
};

class A : virtual public final
{
public:
    A()
{}
}; class B : public A { public: B() { } };

 

class A 是final的friend,所以A可以調用final的構造函數。

因為A虛繼承了final,往后所有繼承A的子類,都必須自己實例化final,以保證final在對象中的唯一性

所以,B繼承A后,需要自己調用虛繼承的父類final的構造函數。顯然,B不是final的友元,不能訪問private中的構造函數。

(注意,將上面的final的構造函數換成了析構函數~final()后,在VS2013中能通過編譯,讀者想想為什么呢?)


免責聲明!

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



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