抽象类的方差

Contravariance on abstract classes

本文关键字:方差 抽象类      更新时间:2023-10-16

我想在C++上创建一个漂亮的接口,在这个接口上,每个实现都需要在其自身上定义添加。

我想做这样的事情:

    class A{
        ...
        virtual A& operator+(const A& other) =0;
        ...
    }
    // this is my interface or abstract class.

    class B : A{
        ...
        B& operator+(const B& other);
        ...
    }
    // this is the kind of implementation i would like. a B element can be added by another B element only ! At least this the constraint I am aiming at.

由于c++不接受逆变,所以我的函数B& operator+(const B& other)不实现virtual A& operator+(const A& other)。有什么棘手的(但有点干净…)方法吗?

template<class Y>
class A
{
    virtual Y& operator+=(const Y& other) = 0;
};
class B : A<B>
{
    // must implement B& operator+=(const B& other) else B is abstract
};

是一种方式。这个习语在执行策略时很常见。看见http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

您试图做的事情在任何语言中都是不可能的,因为它没有意义。

的确,在某些语言中,方法在参数类型中是相反的,但这意味着如果方法接受超类型,它就是一个重载。即operator+(const A&)对于operator+(const B&)来说将是过载的。但不是相反。因为当您有两个A实例(让我们称它们为xy)并编写x + y时,将调用该方法,编译器无法知道两者是否属于同一子类型,因为该信息仅在运行时可用。所以在运行时是你唯一可以检查的时间

因此:

  1. 如果您确实需要一个接口,并且将以多种形式使用它,那么操作员必须获取该接口,并在运行时检查它是否获得了兼容的实例(但这不会激发对设计的信任)
  2. 如果您不需要以多态的方式使用它,那么根本不需要定义接口。只需在将要使用它的模板中使用+(如果它不是多态的,它必须是一个模板),当它没有定义时,编译器就会发出bitch。您可以编写一个概念检查类来尽早发现并避免模板扩展堆栈过深的错误