C++設(shè)計(jì)類(lèi)不能被繼承的方法實(shí)例講解
首先想到的是在C++中,子類(lèi)的構(gòu)造函數(shù)會(huì)自動(dòng)調(diào)用父類(lèi)的構(gòu)造函數(shù)。同樣,子類(lèi)的析構(gòu)函數(shù)也會(huì)自動(dòng)調(diào)用父類(lèi)的析構(gòu)函數(shù)。要想一個(gè)類(lèi)不能被繼承,只要把它的構(gòu)造函數(shù)和析構(gòu)函數(shù)都定義為私有函數(shù)。那么當(dāng)一個(gè)類(lèi)試圖從它那繼承的時(shí)候,必然會(huì)由于試圖調(diào)用構(gòu)造函數(shù)、析構(gòu)函數(shù)而導(dǎo)致編譯錯(cuò)誤。
可是這個(gè)類(lèi)的構(gòu)造函數(shù)和析構(gòu)函數(shù)都是私有函數(shù)了,怎樣才能得到該類(lèi)的實(shí)例呢?可以通過(guò)定義靜態(tài)來(lái)創(chuàng)建和釋放類(lèi)的實(shí)例?;谶@個(gè)思路,可以寫(xiě)出如下的代碼:
///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public :
static FinalClass1* GetInstance()
{
return new FinalClass1;
}
static void DeleteInstance( FinalClass1* pInstance)
{
delete pInstance;
pInstance = 0;
}
private :
FinalClass1() {}
~FinalClass1() {}
};
這個(gè)類(lèi)是不能被繼承,但在總覺(jué)得它和一般的類(lèi)有些不一樣,使用起來(lái)也有點(diǎn)不方便。比如,只能得到位于堆上的實(shí)例,而得不到位于棧上實(shí)例。
能不能實(shí)現(xiàn)一個(gè)和一般類(lèi)除了不能被繼承之外其他用法都一樣的類(lèi)呢?辦法總是有的,不過(guò)需要一些技巧。請(qǐng)看如下代碼:
///////////////////////////////////////////////////////////////////////
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
template <typename T>
class MakeFinal
{
friend T;
private :
MakeFinal() {}
~MakeFinal() {}
};
class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public :
FinalClass2() {}
~FinalClass2() {}
};
這個(gè)類(lèi)使用起來(lái)和一般的類(lèi)沒(méi)有區(qū)別,可以在棧上、也可以在堆上創(chuàng)建實(shí)例。盡管類(lèi)MakeFinal<FinalClass2>的構(gòu)造函數(shù)和析構(gòu)函數(shù)都是私有的,但由于類(lèi)FinalClass2是它的友元函數(shù),因此在FinalClass2中調(diào)用MakeFinal<FinalClass2>的構(gòu)造函數(shù)和析構(gòu)函數(shù)都不會(huì)造成編譯錯(cuò)誤。
但當(dāng)試圖從FinalClass2繼承一個(gè)類(lèi)并創(chuàng)建它的實(shí)例時(shí),卻不同通過(guò)編譯。
class Try : public FinalClass2
{
public :
Try() {}
~Try() {}
};
Try temp;
由于類(lèi)FinalClass2是從類(lèi)MakeFinal<FinalClass2>虛繼承過(guò)來(lái)的,在調(diào)用Try的構(gòu)造函數(shù)的時(shí)候,會(huì)直接跳過(guò)FinalClass2而直接調(diào)用MakeFinal<FinalClass2>的構(gòu)造函數(shù)。非常遺憾的是,Try不是MakeFinal<FinalClass2>的友元,因此不能調(diào)用其私有的構(gòu)造函數(shù)。
基于上面的分析,試圖從FinalClass2繼承的類(lèi),一旦實(shí)例化,都會(huì)導(dǎo)致編譯錯(cuò)誤,因此是FinalClass2不能被繼承。這就滿足了設(shè)計(jì)要求。
C++11中已經(jīng)有了final關(guān)鍵字:它的作用是指定類(lèi)的虛函數(shù)不能被該類(lèi)的繼承類(lèi)重寫(xiě)(override),或者是指定一個(gè)類(lèi)成為一個(gè)不能被繼承的類(lèi)(final class)。
struct A
{
virtual void foo() final;
};
struct B final : A
{
void foo(); // Error: foo cannot be overridden as it's final in A
};
struct C : B // Error: B is final
{
};
上一篇:C++訪問(wèn)注冊(cè)表獲取已安裝軟件信息列表示例代碼
欄 目:C語(yǔ)言
本文標(biāo)題:C++設(shè)計(jì)類(lèi)不能被繼承的方法實(shí)例講解
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3885.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10千萬(wàn)不要被階乘嚇倒
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10C語(yǔ)言 解決不用+、-、&#215;、&#247;數(shù)字運(yùn)算符做加法
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類(lèi)算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載