我正在用C++編寫一個程序,我來自Java並且遇到一些麻煩。 我想有一個基本的抽象類(一個Java接口),它定義了派生類必須實現的一些方法。這個方法可以將派生類型作爲參數,但是在這裏我發現了一個問題。如果我使用基類將它們定義爲基類中的參數,那麼編譯器不會將具有派生類型的重定義視爲重寫,並且派生類仍然是純虛擬的。 解決這種情況的正確方法是什麼? 謝謝!我應該如何實現派生類型爲參數的純虛方法?
0
A
回答
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.
相關問題
- 1. 如何訪問基類中的派生類純虛擬實現?
- 2. 純虛函數派生類
- 3. 該類型品種:: StereoBM必須實現繼承純虛方法
- 4. 如何在派生類中實現純虛函數作爲另一個純虛函數?
- 5. 未實現純虛方法
- 6. 實現純虛類
- 7. 在派生類中實現虛方法的問題
- 8. 類型a必須實現繼承的純虛方法b
- 9. 如何強制派生類來實現,其接收作爲參數派生
- 10. 類型「wxMenuBar」必須實現繼承純虛方法「wxMenuBarBase :: GetLabelTop」
- 11. 爪哇 - 如何實現方法克隆爲基礎,派生類
- 12. 限制傳遞派生類的實例作爲方法參數
- 13. 使用方法聲明純虛在派生類中
- 14. CRTP - 如何從派生類調用基類的實現方法?
- 15. 如何爲派生類實現INotifyPropertyChanged?
- 16. 靜態方法通過虛擬實現調用派生類型? (Android)
- 17. 有什麼方法可以知道C++中的派生類是否已經實現了非純虛函數?
- 18. 在某些派生類中實現虛函數的正確方法是什麼?
- 19. 派生類何時需要實現一個方法爲const?
- 20. 如何執行派生類來實現AS3中的方法?
- 21. 使用/不使用虛擬方法實現純虛擬方法?
- 22. 具有模板派生類的基類純虛函數
- 23. 如何從另一個派生類對象調用派生類虛擬方法
- 24. C++:派生類和虛擬方法
- 25. 子類模板類而無需實現純虛方法
- 26. 任何使Eclipse自動實現純虛函數的方法?
- 27. 純抽象類和派生類型
- 28. 如何實現QML ListModel類似QAbstractListModel派生模型的get方法
- 29. Java在派生類中實現接口方法的方法
- 30. 爲什麼派生類虛擬函數可以調用基類虛函數?編譯器如何實現?
這不應該在Java中工作。反變換要求派生類簽名中的基類簽名和基類型具有派生類型。 – chris