Skip to content

Covariant Return Types

When overriding a virtual function, the return type of the derived class can be a derived type of the base class return type — instead of being exactly the same.

Normal override rule: return type must be identical. Covariant exception: return type can be a derived class pointer/reference.

Problem Without Covariance

cpp
class Dog : public Animal {
public:
    Animal* create() override { // forced to return Animal*
        return new Dog(); // creates Dog but caller gets Animal* back
    }
};
// Caller has to manually cast to use Dog features

Solution — Covariant Return Type

cpp
class Dog : public Animal {
public:
    Dog* create() override { // return Dog* instead of Animal*
        return new Dog();
    }
};

Dog d;
Dog* dog = d.create(); // get Dog* directly — no cast needed!

Real World Example

cpp
class Document {
public:
    virtual Document* clone() { return new Document(*this); }
    void open() { /* ... */ }
};

class SpreadSheet : public Document {
public:
    SpreadSheet* clone() override { return new SpreadSheet(*this); }
    void calculate() { /* ... */ }
};

SpreadSheet s1;
SpreadSheet* s2 = s1.clone(); // no cast needed
s2->calculate();               // can directly use SpreadSheet method

Rules for Covariant Return Types

cpp
// VALID — pointer to derived class
class Base { virtual Base* get(); };
class Derived { Derived* get() override; };

// VALID — reference to derived class
class Base { virtual Base& get(); };
class Derived { Derived& get() override; };

// INVALID — plain types (not pointer/reference) → ERROR
// INVALID — unrelated types → ERROR
// INVALID — non-derived pointer → ERROR

Without vs With Covariance

cpp
// WITHOUT — ugly cast needed
Dog* dog = dynamic_cast<Dog*>(d.create()); // manual cast, unsafe

// WITH — clean and safe
Dog* dog = d.create(); // direct, type-safe

Key Rules Summary

RuleDetail
Must bePointer or reference
Return typeDerived of base return type
Function must bevirtual in base
Plain typesNot allowed
Common use caseclone() pattern

One-liner: "Covariant return types allow an overriding function in a derived class to return a pointer or reference to a more derived type than the base class virtual function, avoiding manual casting."