Covariant return type and type conversion

浪子不回头ぞ 提交于 2019-11-27 06:49:10

问题


s->duplicate() returns an object of type Box*, but I'm getting an error initializing it with Box*. It looks like it's being converted back to Shape*. What is the point of having covariant return types if it's converted back to the base class pointer?:

struct Shape
{
    virtual Shape* duplicate()
    {
        return new Shape;
    }
};

struct Box : Shape
{
    virtual Box* duplicate()
    {
        return new Box;
    }
};

int main()
{
    Shape* s = new Box;
    Box*   b = s->duplicate();
}

Error:

main.cpp:22:12: error: cannot initialize a variable of type 'Box *' with an rvalue of type 'Shape *'
    Box*   b = s->duplicate();
           ^   ~~~~~~~~~~~~~~
1 error generated.

回答1:


Although Box::duplicate is being invoked at runtime (via virtual dispatch), and although Box::duplicate does override Shape::duplicate (covariantly), and although Box::duplicate does return a Box*, you'll still get a Shape* pointer because you are calling duplicate() through a Shape* pointer, and Shape* is the return type of Shape::duplicate(), and the compiler only sees you calling Shape::duplicate, not Box::duplicate.

C++ is not able to dynamically select types, so this is the best it can do. Your Box* is being automatically converted to a Shape* on the way out of Box::duplicate. As Barry said, "it still has to compile at compile time, and at compile time all we know is that it returns a Shape*".

Then, to make it into a Box* again, you need to explicitly cast it (using static_cast or dynamic_cast) because no implicit down-conversion exists.

[C++11: 10.3/7]: The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. [..]

[C++11: 10.3/8]: If the return type of D::f differs from the return type of B::f, the class type in the return type of D::f shall be complete at the point of declaration of D::f or shall be the class type D. When the overriding function is called as the final overrider of the overridden function, its result is converted to the type returned by the (statically chosen) overridden function (5.2.2). [..]

In the standard text, a pertinent example follows.




回答2:


The point isn't to do this:

Box*   b = s->duplicate();

That obviously can't work since Shape::duplicate() returns a Shape*. The point, rather, is to accept a Box* if you're calling duplicate() on a Box directly:

Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box


来源:https://stackoverflow.com/questions/28132869/covariant-return-type-and-type-conversion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!