Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
727 views
in Technique[技术] by (71.8m points)

c++ - Covariant return type and type conversion

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.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...