C ++ Virtual Method返回不同的派生类型

时间:2016-03-02 23:15:20

标签: c++ return-type virtual-functions static-typing covariant-return-types

引用此问题: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()方法的返回值吗?

2 个答案:

答案 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()'方法),就不会出现内部数据问题。

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