1

I am self-learning C++. Following the example of operator + at this link. Suppose I want to modify the operator + a little: instead of adding box1 and box2, I want to input a scaling factor z to the overloaded operator +, so that the intended operator is box1 + z*box2, where z is multiplied by box2.length, box2.height and box2.breadth. How should I modify the code to achieve that? And how would this line change Box3 = Box1 + Box2? Thanks. If this question is related to somewhere else or has been answered, I would appreciate a link.

Below is the original code in that link.

#include <iostream>
using namespace std;

class Box {
   public:
      double getVolume(void) {
         return length * breadth * height;
      }
      void setLength( double len ) {
         length = len;
      }
      void setBreadth( double bre ) {
         breadth = bre;
      }
      void setHeight( double hei ) {
         height = hei;
      }
      
      // Overload + operator to add two Box objects.
      Box operator+(const Box& b) {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
      
   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

// Main function for the program
int main() {
   Box Box1;                // Declare Box1 of type Box
   Box Box2;                // Declare Box2 of type Box
   Box Box3;                // Declare Box3 of type Box
   double volume = 0.0;     // Store the volume of a box here
 
   // box 1 specification
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // box 2 specification
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // volume of box 1
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // volume of box 2
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;

   // Add two object as follows:
   Box3 = Box1 + Box2;

   // volume of box 3
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;

   return 0;
}

Edit: if I change the function declaration to as following to accept two parameters:

Box operator+(const Box& b, int z) {
         Box box;
         box.length = this->length + z*b.length;
         box.breadth = this->breadth + z*b.breadth;
         box.height = this->height + z*b.height;
         return box;
      }

Can I then do this? Box3 = Box1 + (Box2, 5). This does not work apparently.

Tristan Tran
  • 1,351
  • 1
  • 10
  • 36
  • 3
    Implement `operator*(int, Box)`. – sweenish Mar 15 '21 at 15:39
  • 1
    You could create an operator to handle `z*box2` and which returns a special helper-object that you then create an `operator+` overload for. – Some programmer dude Mar 15 '21 at 15:43
  • 2
    By the way, you should declare `Box operator+(const Box& b) const {...}` so expressions like this can work: `Box box = Box(...) + Box(...)` – m88 Mar 15 '21 at 15:43
  • 2
    Also, as [this canonical operator overloading implementations reference](https://en.cppreference.com/w/cpp/language/operators#Canonical_implementations) tells you, the binary operators should be implemented using the compound assignment operator. So `operator+` should be implemented using `operator+=`. – Some programmer dude Mar 15 '21 at 15:46
  • Hi, suppose I change the function to as following (accepting two parameters): ```Box operator+(const Box& b, int z) { Box box; box.length = this->length + z*b.length; box.breadth = this->breadth + z*b.breadth; box.height = this->height + z*b.height; return box; }```, how should I change the line ```Box3 = Box1 + Box2```? – Tristan Tran Mar 15 '21 at 15:46
  • 2
    @TristanTran Every operator has a fixed number of arguments that is allowed. You cannot add additional arguments. You'll have to overload `operator+(const Box&, const Box&)`, `operator*(int, const Box&)`, and `operator*(const Box&, int)` separately. – 0x5453 Mar 15 '21 at 15:50
  • 1
    @Someprogrammerdude That is not the the link says. "The related operators are expected to behave similarly (operator+ and operator+= do the same addition-like operation)." It says if you implement one, you should implement the other. `operator+()` and `operator+=()` don't behave the same, so replacing one with the other won't work. – sweenish Mar 15 '21 at 15:52
  • @0x5453 I see. Thanks for the explanation. – Tristan Tran Mar 15 '21 at 15:52
  • Please invest in [some good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), or take a couple of classes. That should teach you more than simple tutorials can ever do. And one thing a decent book (or tutorial for that matter, actually) should teach you is that you can not change the arguments for operators. And it should also tell you that you should try to keep the semantics of the operators the same as the standard operators. – Some programmer dude Mar 15 '21 at 15:53
  • @Someprogrammerdude Thanks for the book recommendation. – Tristan Tran Mar 15 '21 at 15:54
  • @sweenish [The binary arithmetic operators section](https://en.cppreference.com/w/cpp/language/operators#Binary_arithmetic_operators) says: "Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments" – Some programmer dude Mar 15 '21 at 15:55
  • @Someprogrammerdude That's the link you should have posted the first time. I'm not going to scroll around. Thanks for explaining, though. I'll edit my answer to use this. – sweenish Mar 15 '21 at 16:00

1 Answers1

3

If you want to add two boxes, your operator+() should only add two boxes.

The expression you want to use involves two operations, addition and multiplication. So you need to implement a multiplication operator overload. After that, you just let the order of operations take over. Because you want one operand to be a double or some other number type, it can't be a member function (the first operand would always be the calling object). Here I've implemented a possible solution.

#include <iostream>

class Box {
 public:
  Box() = default;
  Box(double len, double bread, double h)
      : length(len), breadth(bread), height(h) {}
  double getVolume(void) { return length * breadth * height; }
  void setLength(double len) { length = len; }
  void setBreadth(double bre) { breadth = bre; }
  void setHeight(double hei) { height = hei; }

  Box& operator+=(const Box& other) {
    this->length += other.length;
    this->breadth += other.breadth;
    this->height += other.height;

    return *this;
  }

  friend Box operator+(Box lhs, const Box& rhs) {
    lhs += rhs;

    return lhs;
  }

  friend Box operator*(double z, const Box& box) {
    return Box(z * box.length, z * box.breadth, z * box.height);
  }

  friend Box operator*(const Box& box, double z) {
    return z * box;
  }

 private:
  double length = 0.0;   // Length of a box
  double breadth = 0.0;  // Breadth of a box
  double height = 0.0;   // Height of a box
};

// Main function for the program
int main() {
  Box Box1(6.0, 7.0, 5.0);     // Declare Box1 of type Box
  Box Box2(12.0, 13.0, 10.0);  // Declare Box2 of type Box
  Box Box3;                    // Declare Box3 of type Box
  double volume = 0.0;         // Store the volume of a box here

  // volume of box 1
  volume = Box1.getVolume();
  std::cout << "Volume of Box1 : " << volume << '\n';

  // volume of box 2
  volume = Box2.getVolume();
  std::cout << "Volume of Box2 : " << volume << '\n';

  // Add two object as follows:
  Box3 = Box1 + 1.2 * Box2;  // Changed to demonstrate new operator

  // volume of box 3
  volume = Box3.getVolume();
  std::cout << "Volume of Box3 : " << volume << '\n';

  return 0;
}

I made some other changes to the code as well. I added constructors to simplify initialization. I changed the way operator+() works to better align with the recommendations in the standard (link).

The multiplication operator doesn't fit under that umbrella, since your scaling factor cannot (and should not) be implicitly convertible to a Box. It is implemented as a pair of functions to preserve the commutative property of multiplication.

sweenish
  • 4,793
  • 3
  • 12
  • 23