Covariant return type in C++

Having a base_class B and an derived_class D, where D has a function that returns a more specific (derived) class than the base class B.

For example, base_class has a clone function

base_class* base_class::clone()

that returns a pointer to base_class B. If we want to use clone() in D to obtain a pointer to the newly created derived_class D’, the function D.clone() will have covariant return type from B.clone().

Since covariant return type was added to the C++ standard some time later in the its development, older C++ compilers (VC++6 and older, GCC 3.4 and older) do not support covariant return types. The only way to implement clone() in derived_class without using covariant return type is to upcast D’ to base_class before returning it, and later on, if we want to use derived_class specific functions, we will have to downcast* the pointer back, which is slower and troublesome.

With covariant return type, a derived class can return a data type that is more derived/specific than the one it overrides. In the previous example, we will be able to make derived_class::clone() return derived_class* while B.clone() still return base_class*. However, there are restrictions to covariant return types in C++:

The function D::f returns a reference or pointer to a class of type T, and A::f returns a pointer or a reference to an unambiguous direct or indirect base class of T.

The const or volatile qualification of the pointer or reference returned by B::f has the same or less const or volatile qualification of the pointer or reference returned by A::f.

The return type of B::f must be complete at the point of declaration of B::f, or it can be of type B.

Notes:

* Compilers usually won’t allow static downcast in the code, therefore we’ll have to use dynamic cast which is done during runtime. Please refer to my older post for dynamic casting.