2012-12-30 206 views
1

我有一個純虛函數的基類,我有一個派生類,其基類虛函數的定義以及它自己的函數。如何讓基類對象調用派生類非虛函數?

現在我已經指出了基類對象派生類,如:

Base *bc =new Child(); 

我想調用子類的方法使用該對象(沒有定義或父聲明)。

但我得到編譯器錯誤memeberFunction not define in Base class

的代碼是:

class Base 
{ 
public: 
    virtual void method1() = 0; 
}; 

class child : public Base 
{ 
public: 
    virtual void method1() {} 
    void Method2() { /* some implementation */ } 
}; 

我怎樣才能做到這一點?

bc->Method2(); 
+2

請參閱['dynamic_cast'](http://stackoverflow.com/questions/9973708/dynamic-cast-from-base-to-derived)。 – DCoder

+1

如果'bc'是'Base *',*爲什麼*你想要做'bc-> Method2();'?這裏的根本問題是什麼? – Johnsyweb

+0

如果你知道Base *是什麼類型,你可以對你想要的類型做一個'static_cast'。通過使用'type_id'運算符或在Base中返回一個類型(通常枚舉或一個整數作爲ID)的某種虛函數。 –

回答

0

你應該投(使用的dynamic_cast)bcChild *,然後調用Method2()

2

事實上,你想單獨做這件事指出了一個糟糕的設計選擇。在大多數情況下,dynamic_cast的使用也指向了糟糕的設計選擇。還要注意dynamic_cast非常慢,比調用虛擬函數慢得多。順便說一下,您可以使用static_cast來派生派生樹。這當然也是非常罕見的(CRTP就是一個例子)。我還想知道,在這一點上:你怎麼知道對象是一個「孩子」,而不是其他一些基礎派生的對象?如果你確實知道這一點,爲什麼不首先和一個孩子*而不是基地工作? (順便說一下,智能指針,例如unique_ptr。)

0

正確的方法是在基類上實現Method2。如果你想以正確的方式做到這一點,那麼沒有ifs,buts或其他選擇。錯誤的方法是使用dynamic_cast,這將工作,但它仍然不是正確的做法。

如果你絕對不能改變基類,那麼你必須問自己爲什麼它不是基類的一部分。請注意,如果這個類是孩子能夠做的,但是由於某種原因你不能在基類中做,那麼正確的做法是將它作爲一個純虛擬實現,或者實現一個實現做一些合適的「這不是你正在尋找的成員函數」類型的操作。

0

正確的做事方式取決於你想要表達的內容。 假設你的類層次結構是: 類動物

類Kangoroo是一個動物,它可以跳

現在你的動物指針,你只知道它是一種動物。你不能跳它,因爲你知道指針可能指向一頭大象。

三個選項: a)不要讓動物跳躍(改用kangoroo指針) b)使用dynamic_cast。這樣你可以表達:如果它是一個kangoroo,使它跳躍,否則不要 c)向基類(動物)添加jump()並讓Elephant :: jump拋出異常或什麼也不做。

如果您還想讓其他動物跳躍,b解決方案變得非常複雜。還有許多C++程序員不喜歡dynamic_cast。

1

面向對象的原理之一是能夠通過一組通用函數看到一組不同的對象。爲了解決您的問題,您可以使用動態或靜態轉換,但通過這種方式,您可以從窗口中拋出OOP最有用的方面之一。

如果你開始爲對象做許多強制轉換,那麼首先有一個繼承層次(多態)的目的是什麼?

通常,當您在層次結構的基礎上建立大量(純粹)虛擬功能時,OOP將很好地工作;即使這些函數中的一些或許多對某些子類沒有用處。

相關問題