1

参考这个问题: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() 方法的返回值而不进行强制转换吗?

4

2 回答 2

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这里来代替,如果你碰巧对动态类型有误,你可以避免未定义的行为。

于 2016-03-02T23:23:52.020 回答
0

如前所述,您将在 .Get() 调用中遇到编译器错误。如果你想避免这种情况,请分配给基类..

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

只要您通过基类中定义的抽象方法(例如,“toString()”方法)访问“一”和“二”,内部数据就不会有问题。

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

于 2016-03-02T23:33:23.553 回答