6

I'm currently creating a class for complex numbers, and so I figured to make it easier, I'd allow for operations such as a = b + c, instead of a = b.add(c). For example, here is my implementation of addition of two complex numbers:

// An addition operator for the complex numbers
Complex Complex::operator + (Complex n) {
    return Complex(this->real + n.real, this->imaginary + n.imaginary);
}

In this example, adding complex numbers a + b would have the same result as adding b + a, as they should.

However, the issue comes when dealing with non-commutative operators and integers. For example, division by an integer or division of an integer. How could I make it such that both:

a = complex / integer

and

a = integer / complex

give correct responses?

In other words, how can I overload operators in two ways?

Cisplatin
  • 2,860
  • 3
  • 36
  • 56
  • 3
    You shouldn't write your own Complex class (unless you have to for an assignment or something). You should use [`std::complex`](http://en.cppreference.com/w/cpp/numeric/complex). – user1118321 Dec 27 '13 at 04:37
  • 2
    @user1118321 I'm just making it for fun, but thanks, I hadn't heard of that library before. I'll make sure to check out some of their methods for inspiration. – Cisplatin Dec 27 '13 at 04:39

2 Answers2

9

If you write your operator as a free function, rather than a class member, you can specify both operands.

Complex operator/ (int lhs, Complex rhs);
Complex operator/ (Complex lhs, int rhs);

You might have to make them a friend function, if you need to access private members.

(I'll leave it to you to decide whether you need int, or float, or whatever at the front.)

EDIT: A bit fuller example might be:

Complex operator/ (int lhs, Complex rhs) {
    Complex answer;
    double mag = rhs.real*rhs.real+rhs.imag*rhs.imag;
    answer.real = lhs*rhs.real/mag;
    answer.imag = -lhs*rhs.imag/mag;
    return answer;
}

and then a bit later:

f = 6/f;

(again I'm assuming public member variables for ease of use).

tabstop
  • 1,751
  • 11
  • 10
  • I get an error saying the operator "must take exactly one arguement". Maybe because I need a friend function, though I do not know what that is - any chance you could send me a link to explain it (or maybe expand on your answer?) – Cisplatin Dec 27 '13 at 04:44
  • Well, it has to be a free function to take two arguments, not a member function (so you can't say Complex:: at any point). I'll add a fuller example into my answer. – tabstop Dec 27 '13 at 04:55
  • At the risk of sounding pedantic, what tabstop is talking about is called a "non-member overload" of the operator, versus what you did before which were "member overloads," the difference of course being that the ones you did were member functions of the Complex class while tabstop is suggesting overloading the operator outside of the class. Hopefully this makes it clearer to you. – IllusiveBrian Dec 27 '13 at 05:17
  • That's a good point -- you can't include the prototype inside the class either. It's completely outside the class. – tabstop Dec 27 '13 at 05:20
  • Because its a friend function, can it no longer work if the class has a template? – Cisplatin Dec 27 '13 at 19:57
  • @Sim no it just takes more work, something like `friend Complex operator/ (int lhs, Complex rhs)` -- that is, you will have to specify templates where appropriate. And of course that means the free function itself will have to be a template function. – tabstop Dec 27 '13 at 21:29
  • To add: a fuller example of templatex + friends is found at http://stackoverflow.com/questions/18792565/declare-template-friend-function-of-template-class – tabstop Dec 27 '13 at 22:05
3

When you overload an operator for a class, it looks like this: s1.operator+(s2). As you can see, it has an implicit argument, this. Therefore, it only takes one argument. In order to use the version that takes two arguments, they must be free functions. If you want these free functions to see the private variables of your object, you must make them a friend inside your class declaration.

class Object
{
friend Object& operator+(int something, Object& other);
};

// not a member function, don't qualify Object::
Object& operator+(int something, const Object& other)
{
return other.private_variable + something;
}

This is why for example when you overload operator<<, it must be a free function.

// Bad code
class Test
{
    std::ostream& operator<<(std::ostream& os, const Test& test);
};

std::ostream& Test::operator<<(std::ostream& os, const Test& test)
{
}

The implicit this is not an ostream object, and so you cannot chain calls this way.