继承和操作符重载的“无效协变返回类型”错误

时间:2011-09-28 06:56:07

标签: c++ inheritance operator-overloading

我有以下表示数值数组的类

class Array {

protected :
    double *data;   // this will hold the data of the array
    int     n;      // number of elements in the array

public :
    virtual Array operator+ ( double value ) const {
       // return a new array with the argument added to each element
    }

    // other declarations follow here...
};

和另一个继承自前一个类的类,并为每个元素添加一个布尔掩码

class MaskedArray : public Array {

private : 
    bool *mask;   // this holds the boolean mask of the array

public :
    MaskedArray operator+ ( double value ) const {
       // return a new MaskedArray with the argument added to each element
    }

    // other declarations follow here...
}

当我尝试编译时,我得到错误“无效的协变返回类型”,这是正常的,因为两个类中的两个重载运算符具有相同的签名。

我能够通过引用而不是通过值传递继承类的重载运算符的参数来绕过这个问题,因为这会更改函数的签名,同时为两个类保持相同的接口。但我觉得这不是很干净,如果我想从MaskedArray继承怎么办?我会遇到同样的问题。

我希望能够在我的客户端代码中编写这样的东西

Array array;
// populate array here
Array array2 = array + 1.0;

MaskedArray maskedArray;
// populate maskedArray here
MaskedArray maskedArray2 = maskedArray + 1.0

有没有比我的“黑客”更优雅的方式来实现这个目标?

3 个答案:

答案 0 :(得分:1)

Covariant 表示被覆盖的虚函数的返回类型是从基类函数的返回类型继承的。

但是:虽然协方差通常由C ++支持,但该标准仅在返回指针或引用时才允许协方差。 operator+按值返回 ,这就是您收到编译器错误的原因。这不是运营商特有的,但适用于所有功能。

删除virtual关键字将消除编译器错误。但是,如果您这样做,请记住将operator+应用于Array引用或指针,实际引用MaskedArray会返回Array(因此不包含mask成员。如果您将其投放到MaskedArray,则原始mask会丢失。

答案 1 :(得分:0)

您的问题的解决方法可能是使用包含而不是继承:

class MaskedArray {

private : 
    Array array;
    bool *mask;   // this holds the boolean mask of the array

public :
    MaskedArray operator+ ( double value ) const {
       // return a new MaskedArray with the argument added to each element
    }

    // delegate public functions
}

当然,现在MaskedArray不能使用Array的受保护成员(在很多情况下,这是一件好事)并且必须委托公共接口。

答案 2 :(得分:0)

首先,您报告的有关协变结果的错误与显示的代码不一致

它只出现在虚拟成员函数中,并且在我所写的代码中,没有这样的函数。

将来不要再浪费时间了解您的真实代码的错误,并展示一些幻想代码

无论如何,治愈:在真实代码中,只需删除virtual一词。

另外,建议:使用std::vector来保存数据并负责分配,复制和解除分配。