C++ 中的协变返回类型到底是什么?

use*_*176 3 c++ virtual inheritance vector covariant

当我尝试执行此操作时出现编译错误:

class A
{
    virtual std::vector<A*> test() { /* do something */ };
}

class B: public A
{
    virtual std::vector<B*> test() { /* do something */ };
}
Run Code Online (Sandbox Code Playgroud)

我假设 A 和 B 是协变类型,因此 A* 和 B* 也应该是(正确的?)通过推断,我本来期望 和 也std::vector<A*>应该std::vector<B*>是协变的,但情况似乎并非如此。为什么?

Ben*_*igt 6

协变返回类型允许派生类中重写的虚拟成员函数返回不同类型的对象,只要它可以按照与基类的返回类型相同的方式使用即可。计算机科学家(从芭芭拉·利斯科夫(Barbara Liskov)开始)对“可以以同样的方式使用”有一个理论定义:可替代性

不,std::vector<B*>不是 的子类型std::vector<A*>,也不应该是。

例如,std::vector<B*>不支持该push_back(A*)操作,因此不可替代。

C++ 根本不尝试推断模板的子类型关系。仅当您实际专门化一种关系并指定基类时,这种关系才会存在。其原因之一是,即使在理论上协变(基本上是只读)的接口上,C++ 的版本实际上比里氏替换更强——在 C++ 中,兼容性必须存在于二进制级别。由于相关对象集合的内存布局可能与子对象放置不匹配,因此无法实现这种二进制兼容性。协变返回类型仅限于指针或引用也是二进制兼容性问题的结果。派生对象可能不适合为基本实例保留的空间......但它的指针可以。