开发者

inheritance and "invalid covariant return type" error on operator overloading

开发者 https://www.devze.com 2023-04-07 23:28 出处:网络
I have the following class representing numerical arrays class Array { protected : double *data;// this will hold the data of the array

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 i开发者_StackOverflow中文版nherit from 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 ?


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. operator+ returns by value, that's why you get the compiler error. That is not specific to operators but applies to every function.

Removing the virtual keyword will eleminate the compiler error. 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).


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.


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.

Also, word of advice: use a std::vector to hold the data and take care of allocation, copying and deallocation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号