實現一個無法被繼承的C++類

LaoJiu_發表於2017-05-30

一個類不能被繼承,也就是說它的子類不能構造父類,這樣子類就沒有辦法例項化整個子類從而實現子類無法繼承父類。我們可以將一個類的建構函式宣告為私有,使得這個類的建構函式對子類不可見,那麼這個類也就不能繼承了。但是,這引出一個問題,客戶程式豈不是也無法例項化這個類了?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的同時,定義友元函式來幫助構造類的例項。

class CParent
{
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的友元屬性不能被繼承。假設有一個輔助類CNoHeritanceCParentCNoHeritance類的友元。還要假設一個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

相關文章