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 ()'方法),您将不会遇到内部数据问题。

如果您打算在基类的所有实例中处理相同的数据,则可能需要考虑使用模板类。