- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
当我尝试这样做时出现编译错误:
class A
{
virtual std::vector<A*> test() { /* do something */ };
}
class B: public A
{
virtual std::vector<B*> test() { /* do something */ };
}
我假设 A 和 B 是协变类型,因此 A* 和 B* 也应该是(正确的?)根据推论,我预计 std::vector<A*>
和 std::vector<B*>
也应该是协变的,但事实似乎并非如此。为什么?
最佳答案
协变返回类型允许派生类中重写的虚拟成员函数返回不同类型的对象,只要它可以以与基类的返回类型相同的方式使用。计算机科学家(自 Barbara Liskov 以来)对“可以以相同方式使用”有一个理论定义:可替代性。
不,std::vector<B*>
不是 std::vector<A*>
的子类型,也不应该。
例如,std::vector<B*>
不支持 push_back(A*)
操作,所以它是不可替代的。
C++ 根本不会尝试推断模板的子类型关系。仅当您实际专门化一个并指定一个基类时,这种关系才会存在。一个原因是,即使在理论上协变(基本上是只读)的接口(interface)上,C++ 的版本实际上比 Liskov 替换更强大——在 C++ 中,兼容性必须存在于二进制级别。由于相关对象集合的内存布局可能与子对象放置不匹配,因此无法实现这种二进制兼容性。协变返回类型仅限于指针或引用也是二进制兼容性问题的结果。派生对象可能不适合为基础实例保留的空间……但它的指针可以。
关于c++ - C++ 中的协变返回类型到底是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25813435/
在我的设置中,我试图有一个界面 Table继承自 Map (因为它主要用作 map 的包装器)。两个类继承自 Table - 本地和全局。全局的将有一个可变的映射,而本地的将有一个只有本地条目的映射。
Rust Nomicon 有 an entire section on variance除了关于 Box 的这一小节,我或多或少地理解了这一点和 Vec在 T 上(共同)变体. Box and Vec
我是一名优秀的程序员,十分优秀!