More C++ Idioms/Covariant Return Types

Covariant Return Types
edit

Intent edit

Avoid unnecessary casting of the derived value returned from an overridden method in a derived class.

Also Known As edit

Motivation edit

In 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 edit

C++ 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.

Known Uses edit

Related Idioms edit

References edit