# Compound Assignment Operators¶

Tip

If a class defines +, -, *, and /, then it is a good practice to also define the corresponding compound assignment operators, +=, -=, *=, and /=.

The compound assignment operators provide a shorthand, e.g.:

a += b


is the same as

a = a + b


So when we overload the operator, we not only need to do the arithmetic operation, but we need to return a reference to the object we are operating on.

Back to our vector class, this means that our overloaded operator += will have the form:

Vector2d& operator+= (const Vector2d& vec) {
x += vec.x;
y += vec.y;
return *this;
}


(since this is a pointer, we dereference it and return it via reference).

Here’s a full implementation (adding to our previous vector2d.H:

Listing 71 updated vector2d.H
#ifndef VECTOR_2D_H
#define VECTOR_2D_H

#include <iostream>
#include <cmath>

class Vector2d {

private:

// our member data

double x;
double y;

public:

// default constructor

Vector2d()
: x{0.0}, y{0.0}
{}

// another constructor

Vector2d(double _x, double _y)
: x{_x}, y{_y}
{}

// the destructor

~Vector2d() {}

// copy and assignment constructors -- we don't need to define them, but we
// explicitly say to use the default

//Vector2d(const Vector2d& vec) = default;
Vector2d(const Vector2d& vec)
: x(vec.x), y(vec.y) {}

// assignment here means that we want to set our current class's values to
// those to the right of the = -- that's the Vector2d coming in through the
// argument list

//Vector2d& operator= (const Vector2d& vec) = default;
Vector2d& operator= (const Vector2d& vec) {
x = vec.x;
y = vec.y;
return *this;
}

// setters

inline void set_x(double _x) {x = _x;}

inline void set_y(double _y) {y = _y;}

// operators

Vector2d operator+ (const Vector2d& vec) {
Vector2d vec_out(x + vec.x, y + vec.y);
return vec_out;
}

// subtract two vectors

Vector2d operator- (const Vector2d& vec) {
Vector2d vec_out(x - vec.x, y - vec.y);
return vec_out;
}

// unary minus

Vector2d operator- () {
Vector2d vec_out(-x, -y);
return vec_out;
}

// multiplication

// vec * a

Vector2d operator* (double a) {
Vector2d vec_out(a * x, a * y);
return vec_out;
}

// a * vec -- needs to be a friend

friend Vector2d operator* (double a, const Vector2d& vec);

// division by a scalar

Vector2d operator/ (double a) {
Vector2d vec_out(x / a, y / a);
return vec_out;
}

// compound operators

Vector2d& operator+= (const Vector2d& vec) {
x += vec.x;
y += vec.y;
return *this;
}

Vector2d& operator-= (const Vector2d& vec) {
x -= vec.x;
y -= vec.y;
return *this;
}

Vector2d& operator*= (double a) {
x *= a;
y *= a;
return *this;
}

Vector2d& operator/= (double a) {
x /= a;
y /= a;
return *this;
}

// comparison operators

bool operator== (const Vector2d& vec) const {
return x == vec.x && y == vec.y;
}

bool operator!= (const Vector2d& vec) const {
return x != vec.x || y != vec.y;
}

double abs() {
return std::sqrt(x * x + y * y);
}

double dot(const Vector2d& vec) {
return x * vec.x + y * vec.y;
}

// << and >> are not class members, but need access to the member data

friend std::ostream& operator<< (std::ostream& os, const Vector2d& v);
friend std::istream& operator>> (std::istream& is, Vector2d& v);
};

std::ostream& operator<< (std::ostream& os, const Vector2d& vec)
{
os << "(" << vec.x << ", " << vec.y << ")";
return os;
}

std::istream& operator>> (std::istream& is, Vector2d& vec)
{
is >> vec.x >> vec.y;
return is;
}

Vector2d operator*(double a, const Vector2d& vec) {
Vector2d vec_out(a * vec.x, a * vec.y);
return vec_out;
}

#endif


and here’s a driver:

Listing 72 updated compound_test_vectors.cpp
#include <iostream>

#include "vector2d.H"

int main() {

// vectors displancing N, E, S, W

Vector2d v_north(0.0, 1.0);
Vector2d v_east(1.0, 0.0);
Vector2d v_south(0.0, -1.0);
Vector2d v_west(-1.0, 0.0);

// test compound addition -- if we sum up the four vectors above,
// we should get zero

Vector2d v1;
v1 += v_north;
v1 += v_east;

std::cout << "compound addition (intermediate result): " << v1 << std::endl;
v1 += v_south;
v1 += v_west;

std::cout << "compound addition (final result): " << v1 << std::endl;

// test compound subtraction

Vector2d v2(1.0, 1.0);
v2 -= v_north;

std::cout << "compound subtraction: " << v2 << std::endl;

// test compound multiplication

Vector2d v3(2.0, 4.0);
v3 *= 4;

std::cout << "compound multiplication: " << v3 << std::endl;

// test compound division

Vector2d v4(1.0, -5.0);
v4 /= 2;

std::cout << "compound division: " << v4 << std::endl;

}