25

I wanted to know why C++ does not support co-variance in parameters like in example below or if there is a way to achieve it?

class base {
public:
virtual base* func(base * ptr) { return new base(); }
};

class derived : public base {
 public:
 virtual derived* func(derived * ptr) override { return new derived(); } //not allowed
};
  • 8
    A more interesting question would be why is contra-variance on the arguments not supported. – David Rodríguez - dribeas Aug 06 '12 at 02:02
  • Related question: https://stackoverflow.com/questions/53655187/c-covariance-or-contravariance-in-parameters – franckspike Dec 06 '18 at 15:57
  • My guess is, this is a function that will be called rarely. If so, use a `dynamic_cast` to get the derived value; this also gives you a chance to throw an exception for a bad argument. – Spencer Nov 25 '19 at 16:22

1 Answers1

23

The return type is permissible since derived inherits from base, but the function parameter can't work - not all base instances will be a derived also. What's supposed to happen in the cases where func is called on a pointer to base with a parameter that's not a derived? The most derived implementation isn't callable.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • 10
    Which violates the liskov substitution principle. – Jesse Good Aug 06 '12 at 00:24
  • Is there a workaround ? In Java/C# you can just use a cast but in C++, your object will be sliced. – Winter Jan 11 '17 at 17:29
  • 3
    @Winter there is no slicing unless you pass by value (and pass by value would be weird with polymorphic functions which is the question here). Pass by pointer (as in the question) or reference/shared_ptr/unique_ptr will all work and be castable without any slicing as with any other OO language. The only question is which cast to use to guarantee safety and fit your type hierarchy which boils down to a choice between either dynamic_cast or static_cast and a stern warning to users not to break the unwritten contract you're imposing. Possibly you want to revisit your design decisions though. – Flexo Jan 11 '17 at 17:41