繁体   English   中英

C ++:如何在没有强制转换的情况下避免继承类中的“无效协变返回类型”?

[英]C++: How can I avoid “invalid covariant return type” in inherited classes without casting?

我有一个相当复杂的类层次结构,其中类是相互依赖的:有两个抽象类A和C,它们分别包含一个返回C和A实例的方法。 在他们继承的类中,我想使用一个co-variant类型,在这种情况下是一个问题,因为我不知道一种方法来转发声明继承关系。

我得到一个“test.cpp:22:错误:'虚拟D * B :: outC()'的无效协变返回类型” - 错误,因为编译器不知道D是C的子类。

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实例时,您无法分辨它是哪种C(D或其他)。 因此,如果将B指针(由于对派生类的调用产生但在编译时不知道它)存入A指针,我不确定所有内存都是正确的。

当您在多态类型上调用方法时,运行时环境必须检查对象的动态类型,并移动指针以适应您的类层次结构。 我不确定你应该依靠协方差。 看看这个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM