抽象类的逆差异

时间:2014-11-10 15:14:01

标签: c++ abstract-class contravariance function-parameter

我想在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)。这样做的方法有点棘手(但有点干净......)吗?

2 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:5)

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

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

所以:

  1. 如果您确实需要一个接口并且将以多态方式使用它,那么运营商必须接受该接口并在运行时检查它是否具有兼容的实例(但这不会激发对设计的信任)。
  2. 如果您不需要以多态方式使用它,请不要费心定义界面。只需在将要使用它的模板中使用+(如果它不是多态的,它必须是模板)并且编译器在未定义时会发出婊子。您可以编写concept check class以尽早找到并避免使用太深的模板扩展堆栈时出现错误。