在C++中如何阻止類(lèi)被繼承詳解
這個(gè)話題是源自于一個(gè)面試題,我在網(wǎng)上查了一下有不少這方面的解說(shuō)!我自己整理了一下,選擇了一個(gè)自認(rèn)為是最優(yōu)方案!
我們從最簡(jiǎn)單的開(kāi)始:
首先,大家都知道要阻止類(lèi)被實(shí)例化,可以通過(guò)使用private or protected 關(guān)鍵字來(lái)聲明默認(rèn)構(gòu)造函數(shù)。那么在阻止類(lèi)被繼承的時(shí)候,我們需要用到這個(gè)技巧。其次,阻止類(lèi)被繼承還需要使用private來(lái)控制繼承的基類(lèi)。
namespace SamplePrivate { #ifdef NDEBUG class Sealed { protected: Sealed() {}; friend class SampleSealedClass; // 設(shè)置友類(lèi),以便訪問(wèn)Sealed的構(gòu)造函數(shù) }; class SampleSealedClass : private virtual Sealed { }; #else class SampleSealedClass {} #endif }
這樣我們就可以實(shí)例化SampleSealedClass,并且還不用擔(dān)心被繼承了。不過(guò)還是要解釋一下為什么阻止了繼承?
當(dāng)我們寫(xiě)出下面的代碼時(shí),編譯器在編譯過(guò)程中做了什么呢?
class subclass : public SampleSealedClass { };
首先,當(dāng)你在實(shí)例化subclass的時(shí)候,會(huì)先調(diào)用SampleSealedClass的構(gòu)造函數(shù),而在這之前會(huì)調(diào)用Sealed類(lèi)的默認(rèn)構(gòu)造函數(shù),但是我們發(fā)現(xiàn)Sealed是不能被實(shí)例化的,并且通過(guò)private virtual的繼承只能被SampleSealedClass調(diào)用,因此這很好的阻止了類(lèi)被繼承。但是這里我們只能完成一個(gè)類(lèi)被不被繼承,那么是否有更好的方法來(lái)實(shí)現(xiàn)阻止任意類(lèi)被繼承呢?
那就需要用到模板了:
#ifdef NDEBUG namespace SealedClasses { class Sealed { protected: Sealed() {} }; template<class T> class TypeWapper { public: typedef T type; }; } template<typename T> class BaseSealed : private virtual SealedClasses::Sealed { friend class SealedClasses::TypeWapper<T>::type; }; #else template<typename T> class BaseSealed { }; #endif
這里的TypeWapper主要是將外部類(lèi)型傳遞到SealedClasses的,從而能得到訪問(wèn)Sealed構(gòu)造函數(shù)的能力。不過(guò)這段代碼在GCC4.0中通過(guò)編譯,而在vs2008中不能通過(guò)。可以向下面這樣來(lái)引用:
class subclass : BaseSealed<subclass> { public: subclass() { cout << "subclass" << endl; } }; // 下面這個(gè)會(huì)編譯失敗 class ssubclass : public subclass { public: ssubclass() { cout << "ssubclass" << endl; } };
將想法付諸于實(shí)踐,借此來(lái)影響他人是一個(gè)人存在的真正價(jià)值
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++ namespace相關(guān)語(yǔ)法實(shí)例分析
這篇文章主要介紹了C++ namespace相關(guān)語(yǔ)法實(shí)例分析,對(duì)C++初學(xué)者有很好的參考借鑒價(jià)值,需要的朋友可以參考下2014-08-08VC++ 中ListCtrl經(jīng)驗(yàn)總結(jié)
這篇文章主要介紹了VC++ 中ListCtrl經(jīng)驗(yàn)總結(jié)的相關(guān)資料,需要的朋友可以參考下2015-06-06C++ Boost命令行解析庫(kù)的應(yīng)用詳解
命令行解析庫(kù)是一種用于簡(jiǎn)化處理命令行參數(shù)的工具,它可以幫助開(kāi)發(fā)者更方便地解析命令行參數(shù)并提供適當(dāng)?shù)膸椭畔?本文主要介紹了不同的命令行解析庫(kù)和它們?cè)贑++項(xiàng)目中的應(yīng)用,希望對(duì)大家有所幫助2023-11-11Qt之實(shí)現(xiàn)圓形進(jìn)度條的示例代碼
在平時(shí)做頁(yè)面開(kāi)發(fā)時(shí),有些時(shí)候會(huì)用到圓形進(jìn)度條,本文主要介紹了Qt之實(shí)現(xiàn)圓形進(jìn)度條的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10C語(yǔ)言實(shí)現(xiàn)通訊錄系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)通訊錄系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07淺談C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換
這篇文章主要介紹了C++為什么非要引入那幾種類(lèi)型轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03詳解如何用c++實(shí)現(xiàn)平衡二叉樹(shù)
平衡二叉樹(shù)(Balanced Binary Tree)又被稱為AVL樹(shù)(有別于AVL算法),由前蘇聯(lián)的數(shù)學(xué)家Adelse-Velskil和Landis在1962年提出的高度平衡的二叉樹(shù),根據(jù)科學(xué)家的英文名也稱為AVL樹(shù)。本文介紹了它的原理和如何用C++代碼來(lái)實(shí)現(xiàn)2021-06-06