![](/img/trans.png)
[英]Do I have to override every function in base class, if I want to change the return type of a function?
[英]Override function that return base type
我有兩節課。 基類Parent
類和派生類Child
。 Class Parent
具有返回其類類型的純虛函數。 如何在派生類中覆蓋它?
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
Child* OverrideMe(Child* func) override;
};
我試過Child* OverrideMe(Child* func) override;
但我最終得到的錯誤是它沒有覆蓋基類成員。
如果C ++具有完全協方差和逆變支持,那么正確的關系將是輸入中的逆變和輸出中的協變 。 即:
struct Organism { };
struct Animal : Organism {
virtual Animal* OverrideMe(Animal* ) = 0;
};
struct Dog : Aniaml {
Dog* OverrideMe(Organism* ) override { ... }
↑↑↑ ↑↑↑↑↑↑↑↑
covariant contravariant
};
這看起來有點不直觀,但確實有意義。 如果您期待Animal*
,您應該能夠處理任何Animal*
( Dog*
符合條件)。 相反,如果你正在對Animal*
進行一些操作,你只需要一個可以采用Animal*
的操作 - 並且一個Organism*
的操作在這方面有資格。
請注意,如果輸入的是共同的變體,這將打破類型系統。 考慮類似的事情;
Animal* a = new Dog;
a->OverrideMe(new Cat);
如果Dog::OverrideMe
被允許Dog*
,那將失敗 - Cat*
不是Dog*
! 因此,允許使用Animal*
......或任何比它更通用的東西(例如Organism*
),因為所有這些都可以正常工作。
C ++ 不具有逆變支持輸入,只有協方差輸出。 所以你可以寫:
Dog* OverrideMe(Animal* ) override { ... }
要么:
Animal* OverrideMe(Animal* ) override { .... }
但沒有別的。
函數參數的類型和函數的cv限定符必須相同。 所以你可以使用
Child* OverrideMe(Parent* func) override;
您沒有覆蓋此處,因為您的OverrideMe
函數不會接受與您嘗試覆蓋的基類中的函數相同的參數:
class Parent
{
public:
virtual Parent* OverrideMe(Parent* func) = 0;
};
class Child : public Parent
{
public:
virtual Child* OverrideMe(Parent* func) override;
};
這種“聞起來很糟糕”,換句話說,你正在“破壞”正常的“任何對象都應該可以替換為任何其他對象”。
如果在基類中有接口函數,則該函數應在整個類層次結構中采用相同的類型。
所以正確的是:
父* OverrideMe(Parent * func)覆蓋;
(正如juanchopanza所說,你可以返回一個派生類型,但你確定父返回的值總是同一個類嗎?對我來說,這看起來像是可能返回“任何派生對象”的函數類型,在哪種情況下,你要么撒謊,要么以“有趣的效果”結束
如果出於某種原因,在你的情況下這實際上並不“有效”,那么你可能不應該以這種方式使用繼承。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.