c ++中的赋值运算符重载

时间:2015-03-28 16:00:36

标签: c++ operator-overloading assignment-operator

我意识到在Web上重载赋值运算符的示例之后有一些示例,但我花了最后几个小时尝试在我的程序中实现它们并弄清楚它们是如何工作的,我似乎无法做到它和任何帮助将不胜感激。

我正在尝试实现一个重载的赋值运算符函数。

我有3个文件正在运行,Complex.h头文件,Complex.cpp定义文件和我用作测试我的Complex类的驱动程序的.cpp文件。

在Complex.h头文件中,我为赋值运算符的原型:

Complex &operator= (Complex&);

到目前为止,我在.cpp文件中定义重载运算符的原因是:

    Complex &Complex::operator=(Complex& first)
    {
         if (real == first.real && imaginary == first.imaginary)
             return Complex(real, imaginary);

         return first;
    };

我在函数中调用赋值运算符的方式是:

   x = y - z;

具体来说,我的问题是,当我用x = y -z调用重载赋值运算符时,当我返回传入的值并且我无法弄清楚时,它不会将传入的值赋给x为什么从网上的大量例子和解释中,我们将非常感谢任何帮助,我感谢您提前提供任何帮助。

3 个答案:

答案 0 :(得分:1)

我认为您需要以下运算符定义

Complex & Complex::operator =( const Complex &first )
{
     real = first.real;
     imaginary = first.imaginary;

     return *this;
};

您必须返回对分配给的对象的引用。参数也应该是常量参考。在这种情况下,您可以将引用绑定到临时对象,或者您还必须编写移动赋值运算符。

在您的复制赋值运算符的实现中,您不会更改已分配的对象。:)您只需创建一个临时的并返回对此临时或返回引用的引用。

答案 1 :(得分:1)

分配包含两个对象,即要分配的对象和具有所需值的对象。

作业应该:

  • 修改现有对象,即分配给
  • 的对象

作业不应该:

  • 创建新对象
  • 修改具有所需值的对象。

所以,让我们说我们正在处理的对象类型是:

struct S {
  int i;
  float f;
};

执行赋值的函数可能具有签名:

void assignment(S &left_hand_side, S const &right_hand_side);

它会被使用:

S a = {10, 32.0f};

S b;

assignment(b, a);

注意:

  • 左侧对象是可修改的,赋值将修改它,而不是创建一个新对象。
  • 右侧对象,具有所需值的对象,不可修改。

此外,在C ++中,内置赋值操作是表达式而不是语句;它有一个值,可以用作子表达式:

int j, k = 10;

printf("%d", (j = k));

这将j设置为等于k,然后获取该赋值的结果并将其打印出来。需要注意的重要一点是,赋值表达式的结果是分配给的对象。没有创建新对象。在上面的代码中,打印了j的值(为10,因为j刚刚从k分配了值10。)

更新我们之前的赋值函数以遵循此约定会产生如下签名:

S& assignment(S& left_hand_side,S const& right_hand_side);

实现如下:

S &assignment(S &left_hand_side, S const &right_hand_side) {
  // for each member of S, assign the value of that member in 
  // right_hand_side to that member in left_hand_side.
  left_hand_side.i = right_hand_side.i;
  left_hand_side.f = right_hand_side.f;

  // assignment returns the object that has been modified
  return left_hand_side;
}

请注意,此赋值函数不是递归的;它不会在赋值中使用它自己,但它确实使用成员类型的赋值

最后一个难题是让a = b语法工作,而不是assignment(a, b)。为此,您只需将assignment ()作为成员函数:

struct S {
  int i;
  float f;

  S &assignment(S &left_hand_side, S const &right_hand_side) {
    left_hand_side.i = right_hand_side.i;
    left_hand_side.f = right_hand_side.f;
    return left_hand_side
  }
};

left_hand_side参数替换为*this

struct S {
  int i;
  float f;

  S &assignment(S const &right_hand_side) {
    this->i = right_hand_side.i;
    this->f = right_hand_side.f;
    return *this;
  }
};

并将该功能重命名为operator=

struct S {
  int i;
  float f;

  S &operator=(S const &right_hand_side) {
    this->i = right_hand_side.i;
    this->f = right_hand_side.f;
    return *this;
  }
};

int main() {
  S a, b = {10, 32.f};

  S &tmp = (a = b);

  assert(a.i == 10);
  assert(a.f == 32.f);

  assert(&tmp == &a);
}

要知道的另一件重要事情是=符号用于一个未分配的地方:

S a;
S b = a; // this is not assignment.

这是复制初始化'。它不使用operator=。这不是任务。尽量不要混淆两者。

要记住的要点:

  • 赋值修改分配给
  • 的对象
  • 赋值不会修改从中分配的对象。
  • 赋值不会创建新对象。
  • 赋值不是递归的,除非复合对象的赋值在它包含的所有小成员对象上使用赋值。
  • 赋值在修改其值后返回对象
  • 复制初始化看起来有点像赋值,但与赋值没什么关系。

答案 2 :(得分:0)

重载的赋值运算符应如下所示:

Complex &Complex::operator=(const Complex& rhs)
{
     real = rhs.real; 
     imaginary = rhs.imaginary;
     return *this;
};

您还应该注意,如果重载赋值运算符,则应以相同的方式重载Complex的复制构造函数:

Complex::Complex(const Complex& rhs)
{
    real = rhs.real; 
    imaginary = rhs.imaginary;
};