如何在不修改操作数的情况下使用运算符重载链

How do I use a chain of operator overloads without modifying the operands?

本文关键字:运算符 重载 情况下 修改 操作数      更新时间:2023-10-16

假设我们有这个类A:

class A
{
public:
   int a;
   A(int b)
   {
      a = b;
   }
};

我想创建一个+重载,这样我就可以像这样使用它

A a(1),b(2),c(3),&d;
d = a + b + c;

无需修改每个对象的内容。下一个合乎逻辑的事情是每次分配一个新的内存块,如下所示:

A &operator+ (const A &b)
{
   A *c = new A(a+b.a);
   return *c;
}

但这会产生一个新问题:中间结果丢失,导致内存泄漏。我本可以通过创建一个静态函数来轻松解决这个问题,该函数接受三个 A 对象引用并将前两个对象的总和存储在第三个对象中,但我敢打赌,一定有某种方法可以让 + 重载以我想要的方式发生。

所以问题是:有什么方法可以使用运算符重载链,这些运算符重载不会修改操作数而不会导致内存泄漏?

您可以简单地使用按值传递并执行以下操作:

A operator+ (A other) //pass by value
{
   other.a += a;
   return other;
}

或者,由于成员a是可公开访问的,因此您可以(相反应该)将operator+设置为非成员函数,如下所示:

A operator+(A left, A const &right) 
{
   left.a += right.a;
   return left;
}
请注意,第一个参数由

值接受,第二个参数由引用接受。这样,您无需在函数中声明局部变量。您可以使用第一个参数;毕竟它是函数的本地,你可以用它做任何你想做的事情:在这种情况下,我们只需向它添加right.a,然后返回它。


更好的类设计是这样的:(阅读评论)

class A
{
   int a;  //make it private
public:    
   A(int b) : a(b) //use member initialization list
   {
   }
   A& operator+=(A const & other)  //add `+=` overload, as member of the class
   {
      a += other.a;
      return *this;
   }
};
//and make `+` non-member and non-friend 
A operator+(A left, A const & right) 
{
  left += right; //compute this in terms of `+=` which is a member function
  return left;
}

无需在 operator+ 中使用指针。您可以在堆栈中分配中间对象,然后将其返回:

A operator+ (const A &b)
{
   A c(a+b.a);
   return c;
}

或者只是:

A operator+ (const A &b)
{
   return A(a+b.a);
}

甚至更简单:

A operator+ (const A &b)
{
   return a+b.a;
}

由于这隐式地调用了A::A(int).

请注意,我从返回类型中删除了引用。不能返回对本地的非常量引用。

然后你会这样使用它:

A a(1),b(2),c(3),d;
d = a + b + c;

请注意,d不再是引用。