2011-10-31 15 views
7

可能重複:
When should I use C++ private inheritance?實踐中使用非公有C++繼承的頻率如何?

我想使這個社區維基,但看不到按鈕...有人可以增加嗎?

我想不出任何我以非公開方式從班級派生出來的任何情況,而且我無法記起這樣做的副代碼。

我希望聽到現實世界中有用的示例和模式。

+0

你不能再提問題了。如果你願意,你可以標記這些mods爲你做。 – sbi

+0

也在類似的領土http://stackoverflow.com/questions/2090661/protected-inheritance。這兩個問題都表明,有些情況下人們使用非公有繼承,相當可辯(不是我說你在攻擊它!)。 – AAT

回答

6

您的里程可能會有所不同?

硬核的答案是非公有繼承是無用的。

就個人而言,我用它在以下兩種情況:

  • 我想觸發空基地優化如果可能的話(通常,在模板代碼作爲參數傳遞謂詞)
  • 我想在類

來覆蓋virtual功能在任何一種情況下,我於是用private繼承因爲繼承本身是一個實現細節。

我已經看到人們更加寬鬆地使用private繼承,並且在編寫包裝器或擴展行爲時系統地使用,而不是寫作。 C++不提供「簡單」的委託語法,因此可以編寫using Base::method;以立即提供該方法,而不必編寫正確的轉發呼叫(及其所有重載)。我會認爲這是不好的形式,儘管它確實節省了時間。

3

如果您選擇繼承來開發包裝,那麼需要繼承私有繼承。您不再需要或不想從包裝類外部訪問基類的方法和成員。

class B; 
class A 
{ 
public: 
    A(); 
    void foo(B b); 
}; 

class BWrap; 
class AWrap : private A 
{ 
public: 
    AWrap(); 
    void foo(BWrap b); 
}; 

//no longer want A::foo to be accessible by mistake here, so make it private 
2

有時繼承其既不具有任何virtual功能,也不是virtual析構函數(例如STL容器)的類,則可能必須去非public繼承。例如

template<typename T> 
struct MyVector : private std::vector<T> 
{ ... }; 

這將禁止,手柄底座(vector<>)的(指針或引用),以獲得衍生classMyVector<>)的保持:

vector<int> *p = new MyVector<int>; // compiler error 
... 
delete p; // undefined behavior: ~vector() is not 'virtual'! 

因爲,我們在第一線本身得到編譯器錯誤,我們將從後續行中的未定義行爲中保存。

+0

但是,爲什麼你會在這裏使用私有繼承而不是組合;)? –

+0

@MatthieuM。雖然這是一個品味問題,但是作文不會允許像'is_base_of <>'這樣的操作。 :) – iammilind

+0

我知道在C++ 11中SFINAE上下文中的訪問規則發生了一些變化......我不認爲'is_base_of'允許'public'訪問使用基類的知識,並且'私人客戶可以隨時查詢成員本身......那有什麼用? –

2

如果您從沒有虛擬析構函數的類派生,則公共繼承導致該類的用戶可能會調用指向基礎的指針上的delete,從而導致未定義的行爲。
在這種情況下,使用私有繼承是有意義的。

這最常見的例子是從沒有虛擬析構函數的STL容器中私有派生。


C++FAQ具有延伸到許多現實生活的場景私有繼承的一個很好的例子。

一個合法的,長期使用的私有繼承是當你想建立一個Fred類,在一個類威爾瑪使用代碼,並且從類威爾瑪代碼需要從你的新類,弗雷德調用成員函數。在這種情況下,弗雷德在威爾瑪稱非虛擬化,而威爾瑪本身調用(通常是純虛擬),這被弗雷德覆蓋。這對於構圖來說會更難。

代碼示例:

class Wilma { 
protected: 
    void fredCallsWilma() 
    { 
     std::cout << "Wilma::fredCallsWilma()\n"; 
     wilmaCallsFred(); 
    } 
    virtual void wilmaCallsFred() = 0; // A pure virtual function 
}; 

class Fred : private Wilma { 
public: 
    void barney() 
    { 
     std::cout << "Fred::barney()\n"; 
     Wilma::fredCallsWilma(); 
    } 
protected: 
    virtual void wilmaCallsFred() 
    { 
     std::cout << "Fred::wilmaCallsFred()\n"; 
    } 
}; 
2

由於private繼承作爲其唯一已知的使用實施繼承,因爲這總是可以使用遏制,而不是做(這是少用簡單,但更好的封裝的關係),我會說這是使用過經常。

(因爲從來沒有人告訴我什麼protected繼承意味着,假設沒有人知道它是什麼,假裝它不存在。)

+0

+1爲'protected'繼承的代碼片段。我有時會懷疑它是否僅僅爲了一致而被引入(即,因爲'protected'也是一個訪問說明符)。 –

+0

Herb Sutter的「Exceptional C++」中的Item 24提供了我見過的受保護繼承的唯一示例。 – Gorpik

+0

@Matthieu:我認爲受保護的遺產並沒有真正引入到語言中。與此不同,沒有人會打擾它。 ':)' – sbi

0
繼承 當

非公有制(幾乎總是私人的)繼承使用(只)行爲,而不是界面。我主要使用它,但不是專門用於mixin中的 。

有關的話題了很好的討論,你可能需要閱讀巴頓和 Nackman(科學與工程C++:用先進的 技巧與實例介紹,ISBN 0-201-53393-6  儘管這本書的大部分內容都是 適用於所有C++,不僅僅是科學和工程 應用程序。儘管它的日期,它仍然值得一讀。)