C++参数中的协变性

25

我想知道为什么C++不支持像下面的例子中那样使用参数协变,或者是否有一种方法可以实现这个功能?

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
};

9
一个更有趣的问题是为什么不支持参数的逆变。 - David Rodríguez - dribeas
相关问题:https://stackoverflow.com/questions/53655187/c-covariance-or-contravariance-in-parameters - franckspike
我的猜测是,这是一个很少被调用的函数。如果是这样,请使用 dynamic_cast<derived*> 来获取派生值;这也为您提供了抛出无效参数异常的机会。 - Spencer
1个回答

24

由于 derived 继承自 base,因此返回类型是允许的,但函数参数无法工作 - 并非所有的 base 实例都是 derived。在调用指向不是 derived 的参数的指针上的 func 的情况下应该发生什么?最派生的实现无法调用。


10
哪个违反了里氏替换原则。 - Jesse Good
有什么解决方法吗?在Java/C#中,您只需使用转换,但在C++中,您的对象将被切片。 - Winter
4
除非您通过值传递(在这里使用多态函数会很奇怪),否则不会进行切片。使用指针传递(如问题中所述)或引用/ shared_ptr / unique_ptr都可以工作,并且可以像任何其他OO语言一样进行转换,而不会发生切片。唯一的问题是选择使用哪种类型转换以确保安全并适合您的类型层次结构,这归结为在dynamic_cast或static_cast之间进行选择,并警告用户不要打破您正在施加的未经书面约定。也许您需要重新审视您的设计决策。 - Flexo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接