简体   繁体   English

运算符重载时的继承和“无效的协变量返回类型”错误

[英]inheritance and “invalid covariant return type” error on operator overloading

I have the following class representing numerical arrays 我有以下表示数值数组的类

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...
};

and another class inheriting from the previous one and adding a boolean mask for each element 以及从前一个继承的另一个类,并为每个元素添加一个布尔掩码

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...
}

When I try to compile I get the error "invalid covariant return type", which is normal since the two overloaded operators in both classes have the same signature. 当我尝试编译时,出现错误“无效的协变量返回类型”,这是正常现象,因为两个类中的两个重载运算符都具有相同的签名。

I was able to circumvent this problem by passing the argument of the overloaded operator of the inherited class by reference rather than by value, as this changes the signature of the function, while keeping the same interface for both classes. 我可以通过引用而不是按值传递继承的类的重载运算符的参数来解决此问题,因为这会更改函数的签名,同时为两个类保留相同的接口。 But I feel this is not very clean, and what if I wanted to inherit from MaskedArray ? 但是我觉得这不是很干净,如果我想从MaskedArray继承怎么办? I would face the same problem. 我将面临同样的问题。

I want to be able to write stuff like this in my client code 我希望能够在我的客户代码中写这样的东西

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

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

Is there another more elegant way than my 'hack' to achieve this ? 有没有比我的“ hack”更优雅的方法来实现这一目标?

Covariant means that the return type of an overridden virtual function is inherited from the return type of the base class function. 协变意味着重写的虚函数的返回类型是从基类函数的返回类型继承的。

But: Although covariance is generally supported by C++, the standard allows covariance only when returning pointers or references. 但是:尽管C ++通常支持协方差,但是该标准仅在返回指针或引用时才允许协方差。 operator+ returns by value , that's why you get the compiler error. operator+ 按值返回,这就是为什么会出现编译器错误。 That is not specific to operators but applies to every function. 这不是特定于运算符,而是适用于每个功能。

Removing the virtual keyword will eleminate the compiler error. 删除virtual关键字将消除编译器错误。 But if you do so, keep in mind that applying operator+ to an Array reference or pointer, which actually references a MaskedArray returns an Array (and thus does not contain the mask member. If you cast it to a MaskedArray the original mask is lost). 但是,如果要这样做,请记住,将operator+应用于实际引用MaskedArrayArray引用或指针MaskedArray返回一个Array (因此不包含mask成员。如果将其MaskedArray转换为MaskedArray则原始mask会丢失)。 。

A workaround for your issue could be using containment instead of inheritance: 解决您问题的一种方法是使用遏制而不是继承:

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
}

Ofcourse, now MaskedArray can't use the protected members of Array (in a lot of cases, this is a good thing) and the public interface must be delegated. 当然,现在MaskedArray不能使用Array的受保护成员(在很多情况下,这是一件好事),必须委托公共接口。

First, your reported error about covariant result is not consistent with the presented code . 首先,您报告的关于协变结果的错误与提供的代码不一致

It only appears for virtual member functions, and in the presented code, as I write this, there is no such. 它仅出现在虚拟成员函数中,在我编写此代码时,在所提供的代码中没有。

Do not in the future waste our time again by asking about what's wrong with your real code , and presenting some made up fantasy code . 不要在将来通过询问有什么错你真正的代码 ,并提出一些由幻想码再浪费时间了。

Anyway, cure: in your real code , just remove the word virtual . 无论如何,请治愈:在您的真实代码中 ,只需删除单词virtual

Also, word of advice: use a std::vector to hold the data and take care of allocation, copying and deallocation. 另外,建议:使用std::vector来保存数据并注意分配,复制和释放。

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

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