简体   繁体   中英

c++ inheritance: 2 times overloaded operator+ in base class are not working proper in derived class

I wrote my generic class "MyVector" based on std::valarray

//myvector.h
#ifndef MYVECTOR_H
#define MYVECTOR_H
#include <valarray>

template <typename T> 
class MyVector
{
public:
 MyVector(int size){larr.resize(size);}
 MyVector<T>& operator=(const MyVector<T>& other) 
    {
    this->larr=other.larr;
    return *this;
    }
 MyVector<T> operator+ ( const MyVector<T>& rhs);   //body in .cpp file
 template <typename U> 
 MyVector<T> operator+ (const U& val);              //body in .cpp file
protected:
std::valarray larr;
}
#endif
//myvector.cpp

/*****other code*****/

template <typename T>
MyVector<T> MyVector<T>::operator+ ( const MyVector<T>& rhs)
{
    MyVector<T> lv; lv.larr = this->larr + rhs.larr;
    return  lv;  
}

template <typename T>
template <typename U> 
MyVector<T> MyVector<T>::operator+ (const U& val)
{
    MyVector<T> lv; lv.larr = this->larr + static_cast<T> (val);
    return  lv;  
}

/*****other code*****/

Then I try to write a derived class DataVector, with all the functions of MyVector, especially, all my overloaded operators.


#ifndef DATAVECTOR_H
#define DATAVECTOR_H
#include "myvector.h"

class dataVector : public MyVector<int>
{
public:
    dataVector& operator=(const dataVector& other) 
    {
        this->larr=other.larr;
        return *this;
    }
    using MyVector<int>::operator=;
    using MyVector<int>::operator+;
}
#endif

When I try to compile main.cpp,

//main.cpp
#include "datavector.h"
#include "myvector.h"

dataVector datav1(10);
dataVector datav2(10);
dataVector datav3(10);

//if i write:
datav1=datav1 + 10;  //works (gmake and compiler gcc7.5 on ubuntu)
//if i write:
datav3=datav1 + datav2;  //does not work (gmake and compiler gcc7.5 on ubuntu)

I obtain this compiler error:

myvector.cpp: In instantiation of ‘MyVector<T> MyVector<T>::operator+(const U&) [with U = dataVector; T = int]’:
myvector.cpp:xxx:yy: error: invalid static_cast from type ‘const dataVector’ to type ‘int’
     MyVector<T> lv; lv.larr = this->larr + static_cast<T> (val);

If I use MyVector: MyVector3=MyVector1+MyVector2 works well.

Can anyone help me? I know this code isn't well writed, but I'm still learning. thank you.

The problem is that while when you add MyVector to MyVector , MyVector::operator+ ( const MyVector<T>& rhs) matches, but when you add dataVector to dataVector , dataVector::operator+ (const U& val) (inherited from MyVector ) becomes a better match as it accepts anything , not necessarily something covertible to T . There are several possible solutions.

  1. Make dataVector a typedef, like using dataVector = MyVector<int> , if suitable.
  2. Add an operator+ accepting dataVector ; it may call the inherited operator using an explicit cast (like *this + (const MyVector<int> &)rhs ).
  3. Restrict the MyVector::operator+ (const U& val) to accept T only, as suggested by Jarod42.
  4. (The hard way) Restrict the MyVector::operator+ (const U& val) to accept sane types only using SFINAE (like template <typename U, typename = typename std::enable_if<std::is_arithmetic<U>::value>::type> , or maybe is_convertible_to , or whatever appropriate).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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