實現一個無法被繼承的C++類
一個類不能被繼承,也就是說它的子類不能構造父類,這樣子類就沒有辦法例項化整個子類從而實現子類無法繼承父類。我們可以將一個類的建構函式宣告為私有,使得這個類的建構函式對子類不可見,那麼這個類也就不能繼承了。但是,這引出一個問題,客戶程式豈不是也無法例項化這個類了?OK,讓我們參考一下Singleton模式,用一個static函式來幫助建立這個類的例項,問題就解決了!
class CParent
{
private:
CParent(int v){m_v = v;}
~CParent(){}
int m_v;
static CParent * m_instance;
public:
void fun(){cout << "The value is: " << m_v << endl;}
static CParent * getInstance(int v);
};
CParent * CParent::m_instance = NULL;
CParent * CParent::getInstance(int v)
{
m_instance = new CParent(v);
return m_instance;
}
這是一個有效的方法,但是static函式建立出來的例項必然是static的。而且,這個類不能像普通的類那樣構建物件,比如:
CParent c; // impossible
換個思路考慮一下,友元不也是不能被繼承的麼?我們可以把類的建構函式定義為private的同時,定義友元函式來幫助構造類的例項。
{
private:
CParent(int v){m_v = v;}
~CParent();
int m_v;
public:
void fun(){cout << "The value is: " << m_v << endl;}
friend CParent * getInstance(int v);
};
CParent * getInstance(int v)
{
CParent * pinstance = new CParent(v);
return pinstance;
}
這個類也是不能被繼承的,但是出現的問題和前面一樣:我們還是不能像對普通類那樣對待這個類。
現在設想一下,有一個CParent類,我們不希望他能夠被繼承。在友元不能被繼承的思路指引下,我們要考慮讓CParent的友元屬性不能被繼承。假設有一個輔助類CNoHeritance,CParent是CNoHeritance類的友元。還要假設一個CChild類,它試圖去繼承CParent類(如果它有這個能耐的話)。
先把CNoHeritance類的建構函式定義成private,然後將CParent宣告為CNoHeritance的友元類。同時CParent繼承了CNoHeritance類。到目前為止,CNoHeritance除了CParent類以外,誰也無法對它進行訪問和例項化。CChild因為無法繼承CParent的友元特性,所以CChild無法對CNoHeritance直接進行例項化(但是可以通過CParent)。
到目前為止,CParent還是可以被繼承的。這是一個trick.讓我們整理一下思路,下面的圖說明了CNoHeritance, CParent和CChild三個類之間的關係。
如果我們讓CParent類虛繼承CNoHeritance類,根據虛繼承的特性,虛基類的建構函式由最終的子類負責構造。因此CChild如果要想繼承CParent,它必須能夠構造CNoHeritance,這是不可能的!因此,我們的CParent也就終於成為了一個無法繼承的類。
class CNoHeritance
{
private:
CNoHeritance(){}
~CNoHeritance(){}
friend class CParent;
};
class CParent : virtual public CNoHeritance
{
public:
CParent(int v){m_v = v;}
~CParent(){};
private:
int m_v;
public:
void fun(){cout << "The value is: " << m_v << endl;}
};
class CChild : public CParent
{
public:
CChild():CParent(10){}
~CChild(){}
};
需要注意的是,我們這裡引入的CNoHeritance類對整個程式而言,只引入了Private的建構函式和解構函式,所以不會因為可能的菱形繼承帶來二義性.
轉載自:http://blog.csdn.net/lazy_tiger/article/details/2224899
相關文章
- C++ | 類繼承C++繼承
- C++繼承一之公有繼承C++繼承
- js 原型鏈實現類的繼承JS原型繼承
- [C++]繼承和派生類C++繼承
- 類的繼承_子類繼承父類繼承
- UML類圖(上):類、繼承和實現繼承
- ES6建立類的基本語法和繼承實現原理繼承
- 如何判斷一個類是從另一個類繼承繼承
- js類式繼承的實現 非常重要JS繼承
- 類的繼承繼承
- 繼承的實現方式繼承
- js的繼承實現JS繼承
- JavaScript實現類的private、protected、public、static以及繼承JavaScript繼承
- C++中公有繼承、保護繼承、私有繼承的區別C++繼承
- C++繼承C++繼承
- prototype實現繼承繼承
- 實現JavaScript繼承JavaScript繼承
- 從babel實現es6類的繼承來深入理解js的原型及繼承Babel繼承JS原型
- C++ exception 異常類繼承關係C++Exception繼承
- Java之實現多執行緒的方式一 :繼承Thread類Java執行緒繼承thread
- C++中的繼承C++繼承
- JS中繼承的實現JS中繼繼承
- JavaScript實現繼承的方式JavaScript繼承
- C++繼承詳解:共有(public)繼承,私有(private)繼承,保護(protected)繼承C++繼承
- JS原型繼承和類式繼承JS原型繼承
- C++高階教程之繼承得本質:單繼承(一)C++繼承
- ES6 -> Javascript的類與繼承在Babel的實現JavaScript繼承Babel
- Java中類繼承、介面實現的一些細節(長期更新)Java繼承
- javascript類繼承JavaScript繼承
- C++菱形繼承C++繼承
- 《劍指offer》:[48]不能被繼承的類-單例模式繼承單例模式
- C++虛繼承原理與類佈局分析C++繼承
- Javascript如何實現繼承JavaScript繼承
- PostgreSQL用CTE語法+繼承實現拆分大表SQL繼承
- Python類的繼承Python繼承
- 類的繼承圖解繼承圖解
- Java的類與繼承Java繼承
- Swift—類的繼承-備Swift繼承