C ++横向协变:由于类型不完整,返回类型有所不同

问题描述

我正在尝试协方差,并提出了以下示例,该示例至少不使用clang 11和VS2015进行编译:

class Number {
public:
    virtual ~Number () = default;
    virtual Number const * increment()const = 0;
};

class Even;

class Odd : public Number {
public:
    // error: increment() is not covariant because Even is incomplete
    Even const * increment()const; 
};

class Even : public Number {
public:
    Odd const * increment()const;
};

它与Covariant return types,const-ness,and incomplete classes有关,但不是重复的,因为两个重写函数的常量性相同。

该标准还支持吗?

是否有解决此问题的方法或实现类似行为的任何建议?

解决方法

虽然您尝试实现的解决方法可能会变通,但是显示的代码无效。

根据class.virtual#9

如果D :: f的协变返回类型的类类型与B :: f的不同,则D :: f的返回类型的类类型应在该点完成D的声明:: f或应为类类型D ....

在链接的文本中有此规则的示例。

在您的情况下,由于Odd::increment的返回类型不是Number,并且在声明EvenOdd::increment是不完整的,因此代码格式错误

我发现答案不正确,因此是@Brian为您所链接的问题写的deleted answer

,

您可以使用非虚拟接口实现类似的操作(尽管它具有更多的行并且看起来更容易弄乱):

class Number {
public:
    virtual ~Number() = default;
    Number const * increment() const { return do_increment(); }
private:
    virtual Number const * do_increment() const = 0;
};

class Even;

class Odd : public Number {
public:
    Even const * increment() const;
private:
    Number const * do_increment() const override;
};

class Even : public Number {
public:
    Odd const * increment() const { return do_increment(); }
private:
    Odd const * do_increment() const override;
};

inline Even const * Odd::increment() const {
    return static_cast<Even const *>(do_increment());
}