Operators can be overloaded within or outside of classes (unlike Java which doesn’t support operator overloading). There are three main ways to overload operators in C++:

  1. as a free function with access to only the public members,
  2. as a member function with access to all member variables,
  3. as a friend function with access to all member variables (defined either inside or outside of class) Overloading + operator - Stack Overflow

Overloading the assignment operator

#include <iostream>

class Cat {
public:
    int age;

    Cat() : age(5) {
        std::cout << "Default constructor called" << std::endl;
    }

    Cat(const Cat& cat) : age(cat.age){
        std::cout << "Copy constructor called" << std::endl;
    }

    Cat& operator=(const Cat& rhsCat) {
        std::cout << "Assignment operator called" << std::endl;
        return *this;
    }
};

int main() {
    // assignment operator
    std::cout << "\nAssignment operator:" << std::endl;
    cat2 = cat1;
    Cat newCat;
    cat.age = 10;
    newCat = cat;
    std::cout << "Age cat: " << cat.age << std::endl;
    std::cout << "Age newCat: " << newCat.age << std::endl;

    return 0;
}
Default constructor called
Default constructor called
Default constructor called

Assignment operator:
Assignment operator called
Default constructor called
Assignment operator called
Age cat: 10
Age newCat: 5

Why a return value?

Important to remember: The assignment operator returns a reference to the instance via *this. This is only used for chained assignments like cat = cat1 = cat2 and does not mean, that a reference to the right hand side object is copied. The assignment cat = cat1 is equivalent to cat.operator=(cat1). So in the example above, the statement newCat = cat does nothing but to print.

#include <iostream>

class Cat {
public:
    int age;

    Cat() : age(5) {
        std::cout << "Default constructor called" << std::endl;
    }

    Cat(const Cat& cat) : age(cat.age){
        std::cout << "Copy constructor called" << std::endl;
    }

    Cat& operator=(const Cat& rhsCat) {
        std::cout << "Assignment operator called from " << this << std::endl;
        return *this;
    }
};

int main() {
    Cat cat, cat1, cat2;
    // assignment operator
    std::cout << "\nAssignment operator:" << std::endl;
    cat2 = cat1;
    cat2.operator=(cat1);
    Cat newCat;
    cat.age = 10;
    newCat = cat;
    std::cout << "Age cat: " << cat.age << std::endl;
    std::cout << "Age newCat: " << newCat.age << std::endl;
    cat2 = cat1 = cat;
    cat2.operator=(cat1.operator=(cat));

    return 0;
}
Default constructor called
Default constructor called
Default constructor called

Assignment operator:
Assignment operator called from 0x7fff5e8dbc70
Assignment operator called from 0x7fff5e8dbc70
Default constructor called
Assignment operator called from 0x7fff5e8dbc74
Age cat: 10
Age newCat: 5
Assignment operator called from 0x7fff5e8dbc6c
Assignment operator called from 0x7fff5e8dbc70
Assignment operator called from 0x7fff5e8dbc6c
Assignment operator called from 0x7fff5e8dbc70

If the return type of the overloaded assigment operator were void, the only things that would break, are the chained operations.

Categories: