C++:我如何可以避免"无效的协变回归类型",在继承类不铸的?
-
18-09-2019 - |
题
我有一个相当复杂的类层次在这类跨喜欢这取决于每个其他:有两个抽象的类和C包含一个方法,该方法返回的一个实例C和一个,分别。在他们继承的课程我想用一个共同变体类型,这是在这种情况下,一个问题,因为我不知道一种方法向前宣布继承有关的船舶。
我得到一个"测试。cpp:22:错误:无效的协变回归类于'虚拟D*B::outC()'"错误,因为编译器不知道这是一个子类。
class C;
class A {
public:
virtual C* outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class D;
class B : public A {
public:
D* outC();
};
class D : public C {
public:
B* outA();
};
D* B::outC() {
return new D();
}
B* D::outA() {
return new B();
}
如果我改变返回型的B::outC()至C*例编译。是否有任何方式继续B*和D*作为回报类型的继承的课程(这将是直到我有一种方法)?
解决方案
我知道的任何方式的用C具有直接耦合协变构件++。你必须要么加层,或实现协变返回自己。
对于第一种选择
class C;
class A {
public:
virtual C* outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class BI : public A {
public:
};
class D : public C {
public:
BI* outA();
};
class B: public BI {
public:
D* outC();
};
D* B::outC() {
return new D();
}
BI* D::outA() {
return new B();
}
和用于所述第二
class C;
class A {
public:
C* outC() { return do_outC(); }
virtual C* do_outC() = 0;
};
class C {
public:
virtual A* outA() = 0;
};
class D;
class B : public A {
public:
D* outC();
virtual C* do_outC();
};
class D : public C {
public:
B* outA();
};
D* B::outC() {
return static_cast<D*>(do_outC());
}
C* B::do_outC() {
return new D();
}
B* D::outA() {
return new B();
}
请注意,这第二个选项是什么是由编译器隐式进行(有一些静态检查该的static_cast是有效的)。
其他提示
据我所知,没有办法做到这一点没有明确的铸造。问题是,定义类 B
不能知道 D
是一个子类的 C
直到看到一个全面的定义类 D
, 但级的定义 D
不能知道 B
是一个子类的 A
直到看到一个全面的定义类 B
, 等你有一个圆形的依赖。这不可能是解决与前向声明,因为一向宣言,不幸的是,无法指定一个继承关系。
有一个类似的问题在努力实施协变 clone()
方法的使用模板, 我找到可以解决, 但类似解决方案仍然失败,在这里,因为圆形的基准仍然是不可能解决。
您无法做到这一点,由于客户端的期望。当使用C实例,你不能告诉它是(A d或别的东西)的类C。因此,如果你存储在B指针(从派生类的调用产生的,但你没有在编译时知道)为指针,我不知道,所有的记忆的东西将是正确的。
当你调用一个方法上多态类型,运行时环境必须检查动态类型的对象,并将其移动指针,以满足你的类层次结构。我不知道,你应该依靠协方差。看看这个