重载+运算符的继承

时间:2015-09-03 01:39:06

标签: c++ class inheritance operator-overloading

我在继承重载+运算符时遇到问题。 让我举个例子。

class Data{
protected:
    int data[3];
public:
    Data(){
        data[0] = data[1] = data[2] = 0;
    }

    Data operator+(const Data& other)
    {
        Data temp = *this;
        for(int i=0;i<3;i++){
            temp.data[i] += other.data[i]
        }
        return temp;
    }
};

class DataInterited:public Data{
public:

};
/******************Main*****************/
DataInterited d1,d2,d3;
d3 = d1 + d2;  //=> This is compile error

此代码生成编译错误,

  

'operator ='不匹配(操作数类型为'DataInterited'和'Data')

我认为我必须为operator+实施DataInherited,以便它返回DataInherited个实例。 但是通过这种方式,我无法避免代码重复。

有没有办法让d3=d1+d2;行正确,同时避免重复+ operator实现?

2 个答案:

答案 0 :(得分:1)

您需要了解一些事项。

首先,始终将operator+实现为operator+=方面的自由函数。它可以节省代码重复并且效率最高。

其次,DataInherited中没有构造函数可以使用Data作为参数。这很重要,因为Data::operator+的结果是数据,而不是DataInherited

更正后的代码:

#include <iostream>
#include <algorithm>

class Data{
protected:
    int data[3];
public:
    Data(){
        data[0] = data[1] = data[2] = 0;
    }

    Data(const Data& other)
    {
        std::copy(std::begin(other.data), std::end(other.data), data);
    }

    Data& operator=(const Data& other)
    {
        std::copy(std::begin(other.data), std::end(other.data), data);
        return *this;
    }

    Data& operator+=(const Data& other)
    {
        for(int i=0;i<3;i++){
            data[i] += other.data[i];
        }
        return *this;
    }

};

Data operator+(Data left, const Data& right)
{
    return left += right;
}

class DataInterited:public Data{
public:
    DataInterited(Data d = {})
    : Data(std::move(d))
    {}

};

using namespace std;

auto main() -> int
{
    DataInterited d1,d2,d3;
    d3 = d1 + d2;  //=> This is no longer a compile error
    return 0;
}

答案 1 :(得分:-1)

Koenig运营商转发到increment_by功能。

派生类如果需要不同的行为,可以实现自己的increment_by重载。

跳过SFINAE的东西,所以不好的类型会给出错误的错误。

class Data{
public:
  template<class D, class Rhs>
  friend D operator+=(D&& lhs, Rhs&& rhs){
    increment_by(lhs,std::forward<Rhs>(rhs));
    return std::forward<D>(lhs);
  }
  template<class Lhs, class Rhs>
  friend Lhs operator+(Lhs lhs, Rhs&& rhs){
    lhs+=std::forward<Rhs>(rhs);
    return std::move(lhs);
  }
  friend void increment_by(Data& self, Data const&other){
    for(int i=0;i<6;i++){
      self.data[i] += other.data[i];
    }
  }
};

++=都是模板朋友,因此传递的类型可以是派生类。因此输入不会丢失,

如果派生类型需要新行为,

increment_by需要重写。如果没有,请不要管它。

live example

不要不必要地离开这个类型。从base转换为derived基本上抛出派生类型的点。