2012-05-07 68 views
0

據我瞭解,我們無法將派生類對象傳遞給基類繼承的基類引用的原因是由於派生是從Base中私下繼承的,Base的默認構造函數在派生的構造函數之前調用。但是因爲它是私有的,並且不會繼承到Derived,所以我們得到一個編譯器錯誤。私有繼承和派生對象到基礎引用

但是,如果我嘗試爲Base創建一個公共構造函數並私下繼承Derived,然後將公共狀態重新分配給Base的構造函數,它是否允許我將派生實例傳遞給Base引用?

我試了一下,如下所示,

#include <iostream> 

using namespace std; 

class base 
{ 
     public: 
      base(){} 
      void print(){ puts("In base"); } 
}; 

class derived : private base 
{ 
     public: 
      base::base; /* Throws an error - Declaration doesnt declare anything*/ 
      void print(){ puts("In derived"); } 
}; 

void func(base& bRef) 
{ 
} 

int main() 
{ 
    derived dObj; 
    func(dObj); /* Throws an error - 'base' is an inaccessible base of derived */ 
} 

它會因基地:: Base的一個錯誤(宣傳私下繼承的構造爲public)。 是我想要的有效?任何人都可以告訴我嗎?

回答

4

我們不能對繼承的派生對象進行基類引用的原因是因爲這會違反Liskov Substitution Principle:派生對象IS-NOT-A基類對象,因爲它不提供基類public interface。您無法解決此問題

因此,私有繼承是重用實現的一種方式,而不是當您想要製作更專用的類型時。由於這可以在大部分時間內通過組合來完成(即,具有基類的成員而不是私有派生),所以私有繼承可能是不好的代碼異味。

您可以閱讀here(確保遵循所有鏈接)以獲取關於何時私有繼承是一個好選擇的更多信息(摘要:何時沒有其他選擇)。

+0

感謝您的回覆。 –

2

不,指向帶有基類的指針或引用的派生對象是無效的。如果可能的話,那麼私有繼承的全部目的(隱藏派生類從基類繼承它的功能的一部分(或全部)的事實)將是無用的。

假設你在基類中有一個方法foo()。你不希望這個方法被調用。但是如果可以從基類的指針指向對象,那麼也可以調用foo()

Base * ptrBase = &objDerived;  // Let's suppose this would compile 
ptrBase->foo();     // Now we can call foo() (?) 

當你聲明私有繼承時,就好像Derived類與基類沒有關係。只有你,開發者是唯一一個應該「知道」這種關係存在的人,而實際上你應該忘記這一點,因爲這是行不通的。

私有繼承只是作爲一種可重用機制,而不是一種真正的繼承機制。不建議甚至使用它,因爲通過簡單地應用合成就可以獲得更好的結果(即只需在Derived中創建類Base的屬性)。

+0

感謝您的解釋。出於好奇,我有另一個疑問。我知道我們可以在派生類中私有繼承基類時公開基類的公共方法。但是我們可以對基礎的公共構造函數做同樣的事嗎?它有效嗎? –

+0

不,您必須創建一個簡單的構造函數,如:derived():base(){}。 – Baltasarq