More C++ Idioms/Covariant Return Types
Covariant Return Types
edit
Intent
editAvoid unnecessary casting of the derived value returned from an overridden method in a derived class.
Also Known As
editMotivation
editIn C++ a base class determines the method signatures of virtual functions that derived classes might override. The type of the return value in the overridden function is generally same as that of the base class's function. However, this can be limiting if the type returned by the overridden function is substitutable (sub-class) for the type of the base function. Consider the following example.
class Base {
public:
virtual Base * clone() const {
return new Base(*this);
}
};
class Derived : public Base {
public:
virtual Base * clone() const override {
return new Derived(*this);
}
};
Derived *d1 = new Derived();
Base * b = d1->clone();
Derived *d2 = dynamic_cast<Derived *>(b);
if(d2) {
// Use d2 here.
}
The caller of clone knows that the run-time type of the object returned by the function is Derived. However, a dynamic_cast is necessary to downcast the Base pointer to Derived if functions specific to Derived are to be used.
Solution and Sample Code
editC++ allows the derived type to implement an overridden function with return type that is a (pointer to a) sub-type of the return type of the base function. Here's an updated example.
class Base {
public:
virtual Base * clone() const {
return new Base(*this);
}
};
class Derived : public Base {
public:
virtual Derived * clone() const override {
return new Derived(*this);
}
};
Derived *d1 = new Derived();
Derived *d2 = d1->clone();
if(d2) {
// Use d2 here.
}
This alternative is direct and saves unnecessary casts.