3 回答

TA貢獻1862條經(jīng)驗 獲得超7個贊
在某些情況下,是的,只要返回類型與原始返回類型協(xié)變,派生類使用不同的返回類型覆蓋虛擬函數(shù)是合法的。例如,考慮以下內(nèi)容:
class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived: public Base {
public:
virtual Derived* clone() const {
return new Derived(*this);
}
};
在這里,Base定義了一個純虛擬函數(shù)clone,該函數(shù)返回a Base *。在派生的實現(xiàn)中,此虛擬函數(shù)使用的返回類型重寫Derived *。盡管返回類型與基本類型不同,但這是絕對安全的,因為任何時候您都會編寫
Base* ptr = /* ... */
Base* clone = ptr->clone();
調(diào)用to clone()始終會返回指向Base對象的指針,因為即使返回a Derived*,該指針也可以隱式轉(zhuǎn)換為a,Base*并且該操作定義明確。
更一般而言,函數(shù)的返回類型從不視為其簽名的一部分。您可以使用任何返回類型覆蓋成員函數(shù),只要返回類型是協(xié)變的即可。

TA貢獻1744條經(jīng)驗 獲得超4個贊
是。只要它們是協(xié)變的,返回類型就可以不同。C ++標(biāo)準(zhǔn)對此進行了描述(第10.3 / 5節(jié)):
覆蓋函數(shù)的返回類型應(yīng)與覆蓋函數(shù)的返回類型相同或與函數(shù)的類協(xié)變。如果一個函數(shù)D::f覆蓋某個函數(shù)B::f,則滿足以下條件的函數(shù)的返回類型將是協(xié)變的:
兩者都是指向類或指向類98的指針)
返回類型B::f為的類與D::f或返回類型為的類相同,是返回類型為的類的明確的直接或間接基類,D::f并且可以在中訪問D
指針或引用都具有相同的cv限定,并且返回類型的類類型D::f具有與等于或小于返回類型的類類型相同的cv限定B::f。
腳注98指出“不允許使用指向類的多級指針或指向類的多級指針”。
簡而言之,如果D是的子類型B,則in中的函數(shù)的返回類型D需要是中的函數(shù)的返回類型的子類型B。最常見的示例是當(dāng)返回類型本身基于D和時B,但不一定必須如此??紤]一下,在這里我們有兩個單獨的類型層次結(jié)構(gòu):
struct Base { /* ... */ };
struct Derived: public Base { /* ... */ };
struct B {
virtual Base* func() { return new Base; }
virtual ~B() { }
};
struct D: public B {
Derived* func() { return new Derived; }
};
int main() {
B* b = new D;
Base* base = b->func();
delete base;
delete b;
}
之所以起作用,是因為任何的調(diào)用者func都希望有一個Base指針。任何Base指針都可以。因此,如果D::func保證總是返回一個Derived指針,那么它將始終滿足祖先類提出的約定,因為任何Derived指針都可以隱式轉(zhuǎn)換為Base指針。因此,呼叫者將始終得到他們所期望的。
除了允許返回類型改變之外,某些語言還允許覆蓋函數(shù)的參數(shù)類型改變。當(dāng)他們這樣做時,它們通常需要保持不變。也就是說,如果B::f接受Derived*,則將D::f允許接受Base*。后代可以放寬接受的條件,嚴(yán)格要求返回的條件。C ++不允許參數(shù)類型相反。如果更改參數(shù)類型,則C ++會將其視為全新功能,因此您開始陷入重載和隱藏狀態(tài)。有關(guān)此主題的更多信息,請參見Wikipedia中的協(xié)方差和逆方差(計算機科學(xué))。
- 3 回答
- 0 關(guān)注
- 896 瀏覽
添加回答
舉報