How do I use a chain of operator overloads without

2019-02-17 14:27发布

问题:

Let's say we have this class A:

class A
{
public:
   int a;

   A(int b)
   {
      a = b;
   }
};

I would like to create a + overload such that I could use it like this

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

without modifying the content of each object. The next logical thing would be allocating a new chunk of memory each time like this:

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

But this would create a new problem: intermediate results are lost, causing memory leaks. I could have easily solved this problem by making a static function that takes three A object references and stores the sum of the first two in the third, but I'm willing to bet that there must be some way to make + overload happen the way I want.

So the question is: is there any way I could use a chain of operator overloads that do not modify the operands without causing memory leaks?

回答1:

You can simply use pass by value and do this:

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

Or, since the member a is publicly accessible, you can (rather should) make operator+ a non-member function as:

A operator+(A left, A const &right) 
{
   left.a += right.a;
   return left;
}

Notice that the first argument is accepted by value, and second by reference. In this way, you don't need to declare a local variable in the function. You can use the first parameter; after all it is local to the function, you can do whatever you want to do with it: in this case, we just add right.a to it, and return it.


A better design of class would be this: (read the comments)

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;
}


回答2:

There is no need to use pointers inside operator+. You can allocate the intermediate object in the stack and then return it:

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

Or just:

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

Or even simpler:

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

Since this implicitly calls A::A(int).

Note that I removed the reference from the return type. You can't return a non-const reference to a local.

Then you would use it this way:

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

Note that d is no longer a reference.