引用此问题:C++ virtual function return type
让我们考虑以下一组对象。
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 :(得分: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
来避免未定义的行为,如果你对动态类型碰巧出错了。
答案 1 :(得分:0)
如上所述,您将在.Get()调用中遇到编译器错误。 如果你想避免这种情况,请将赋值赋予基类..
ReturnTypeBase * one = objects[0].Get();
ReturnTypeBase * two = objects[1].Get();
只要通过基类中定义的抽象方法访问'one'和'two'(例如'toString()'方法),就不会出现内部数据问题。
如果您打算在基类的所有实例中处理相同的数据,您可能需要考虑使用模板类。