0

I have a Java background and trying to learn C++. I have code like one shown below. I am trying to understand when should I overload the operator like this complex operator+(const complex& c2) and when should I overload the operator like this complex operator+(complex a, complex b). I cannot have both the functions at the same time as the compiler complains about ambiguity so I have commented one out. Both functions (former is a method of the class) produce same result:

#include <iostream>
using namespace std;

//This class is in global scope
class complex {
    private:
        double re, im;

    public: 
        complex(double r, double i): re {r}, im {i} {}
        double real() const { 
            return re;
        }
        void real(double r) {
            re = r;
        }

        double imag() const { 
            return im;
        }
        void imag(double i) {
            im = i; 
        }

        /*
        complex operator+(const complex& c2) {
            cout << "Single arg operator+\n";
            complex c = complex(0, 0);
            c.real(re + c2.real());
            c.imag(im + c2.imag());
            return c;
        }
        */

        complex& operator+=(const complex& c2) {
            cout << "operator+=\n";
            re += c2.real();
            im += c2.imag();
            return *this;
        }

        void print() {
            cout << "Real: " << re << ", Imaginary: " << im << "\n";
        }
};

//This function is in global scope
complex operator+(complex a, complex b) {
    cout << "Double arg operator+\n";
    return a += b;
}

int main() {
    complex c = complex(2, 3);
    complex c2 = complex(2, 3);
    complex c3 = c + c2;
    c.print();
    c += c2;
    c.print();
}

sshekhar1980
  • 327
  • 2
  • 12
  • Separate from your actual question, you probably want `complex operator+(const complex& c2) const` and `complex operator+(const complex &a, const complex &b)`. – Brick May 27 '21 at 19:59
  • 2
    Cliclk on the *The Decision between Member and Non-member* link in the dupe target question to go to the relevant section – NathanOliver May 27 '21 at 20:00
  • Use the first function when defining inside the class, and second for global. The first function implicitly takes the class's instance as the first parameter, while for second, the compiler needs both the objects to operate on. – vikram May 27 '21 at 20:00
  • @Brick `operator+` is taking advantage of pass by value, at least for the first parameter, to provide the new instance that is being added to and then returned. `complex operator+(complex a, const complex &b)` would be a reasonable change though. – user4581301 May 27 '21 at 20:01
  • Yes, @user4581301, the implementation would also have to change if the signature changed. But I think that's part of the answer too. – Brick May 27 '21 at 20:03
  • The complier may optimize some of your extra stuff out, but it's clearer (and certainly not less optimal) to write these options as `complex operator+(const complex& c2) const { return complex(re+c2.re, im+c2.im); }` and `complex operator+(const complex &a, const complex &b) { return complex(a.real()+b.real(), a.imag()+b.imag()); }`. You are calling for a lot of unnecessary steps. Presumably if you're writing a numerical class like this, you want to keep it streamlined. – Brick May 27 '21 at 20:17

0 Answers0