1

參考此問題:C++ virtual function return typeC++虛擬方法返回不同的派生類型

讓我們考慮以下一組對象。

class ReturnTypeBase 
{ 
}; 

class ReturnTypeDerived1 : public ReturnTypeBase 
{ 
public: 
    int x; 
}; 

class ReturnTypeDerived2 : public ReturnTypeBase 
{ 
public: 
    float y; 
}; 

class Base 
{ 
public: 
    virtual ReturnTypeBase* Get() = 0; 
}; 

class Derived1: public Base 
{ 
public: 
    virtual ReturnTypeDerived1* Get() 
    { 
     return new ReturnTypeDerived1(); 
    } 
}; 

class Derived2: public Base 
{ 
public: 
    virtual ReturnTypeDerived2* Get() 
    { 
     return new ReturnTypeDerived2(); 
    } 
}; 

這些對象可以通過以下方式使用嗎?

Base* objects[2]; 

objects[0] = new Derived1(); 

objects[1] = new Derived2(); 

ReturnTypeDerived1* one = objects[0]->Get(); 

ReturnTypeDerived2* two = objects[1]->Get(); 

我假設既然返回類型是協變(?),那上面的對象是合法的C++。相應的Get()方法會被調用嗎?可以指派一個/兩個指針的Get()方法的返回值而不需要轉換嗎?

+0

你是不是指'ReturnTypeDerived1 * one = objects [0] - > Get();'? – wally

+0

@flatmouse是的,幾乎得到了編輯。:D –

+0

你有一個使用案例? – curiousguy

回答

4

該代碼不會按照書面進行編譯。由於objects[0]具有靜態類型Base*,因此調用Get函數會生成一個靜態類型爲ReturnTypeBase*的指針。由於這是一個被覆蓋的虛函數,因此派生類的Get函數將按照您的預期調用,並且返回的指針實際上指向一個ReturnTypeDerived1對象,但編譯器無法證明這一點。您將需要一個轉換:

auto one = static_cast<ReturnTypeDerived1*>(objects[0]->Get()); 
auto two = static_cast<ReturnTypeDerived2*>(objects[1]->Get()); 

如果您ReturnTypeBase多態類型,你可以在這裏使用dynamic_cast來避免不確定的行爲,如果你碰巧是錯的動態類型。

+0

這裏沒有錯誤嗎?不應該'dynamic_cast'是'static_cast'? – wally

+0

@flatmouse你也可以使用'static_cast',但是你無法告訴你是否錯誤的實際類型。 – Brian

+1

'dynamic_cast'不會工作,因爲'ReturnTypeBase'不是一個多態類型。 –

0

正如你所寫,你會在.Get()調用中得到編譯器錯誤。 如果你想避免這種情況,使分配給基類..

ReturnTypeBase * one = objects[0].Get(); 
ReturnTypeBase * two = objects[1].Get(); 

只要你進入「一」和「二」,通過抽象方法在基類中定義的,(如一個「的toString ()'方法),您將不會遇到內部數據問題。

如果您打算在基類的所有實例中處理相同的數據,則可能需要考慮使用模板類。