2015-09-26 82 views
0

我正在用C++編寫一個程序,我來自Java並且遇到一些麻煩。 我想有一個基本的抽象類(一個Java接口),它定義了派生類必須實現的一些方法。這個方法可以將派生類型作爲參數,但是在這裏我發現了一個問題。如果我使用基類將它們定義爲基類中的參數,那麼編譯器不會將具有派生類型的重定義視爲重寫,並且派生類仍然是純虛擬的。 解決這種情況的正確方法是什麼? 謝謝!我應該如何實現派生類型爲參數的純虛方法?

+1

這不應該在Java中工作。反變換要求派生類簽名中的基類簽名和基類型具有派生類型。 – chris

回答

0

你應該在這裏做的是在派生類中創建一個函數,它將基類作爲參數。您可以使用dynamic_cast來確保運行時類型確實是派生類(否則會引發異常)。正如克里斯在他的評論中提到的那樣,逆變是「很難」的。

class Base 
{ 
    public: 
    virtual void fn(const Base &base)=0; 
} 
class Derived:public Base 
{ 
    void fn(const Base &base) 
    { 
     const Derived *derived=dynamic_cast<const Derived *>(&base); 
     if(derived!=nullptr) 
     {//code for derived.. 
     } 

    } 
} 

如果你真的必須有你要求的,你應該去CRTP。我懷疑你真的不需要。如果你真的需要它,Adrian的答案就是你要找的。

請記住,如果您選擇CRTP,您將失去一些繼承的好處。例如,您不能創建基類指針列表(vector <Base *>)。無論何時使用基類(Base<Derived>),您都需要選擇派生類,這可能會失敗。

+0

我會在代碼評論中標記這違反了Liskov原則,因爲我無法在所有Base對象所在的位置使用Derived對象。 – Jens

2

我想你想寫的東西是這樣的:

template<class T> 
class Interface { 
    virtual void Method(T i) = 0; 
}; 

class Implement : public Interface<Implement> { 
    virtual void Method(Implement i) override { 

    } 
}; 

這就是所謂的CRTP

0

你想要做的事情在Java中也不行。在Java中,返回類型可以是協變的,但不是方法的參數。如果您考慮Liskov原則,那實際上是有道理的:如果縮小派生類的契約,您將無法用派生對象替換基礎對象。

解決方案可能需要在設計級別。只是猜測,但這種問題與你想在類上派發的情況以及參數類型有關。如果是這樣的話,看看Visitor pattern.

相關問題