Covariant return type and type conversion
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 ofD::f
differs from the return type ofB::f
, the class type in the return type ofD::f
shall be complete at the point of declaration ofD::f
or shall be the class typeD
. 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.
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