Reputation: 662
Are there any "rules" for what kind of return type member vs non-member functions should have?
I'm building a Complex Class and I thought member functions would be return type references and non-member would be copies. Is this correct?
Complex.h for reference:
#include <iostream>
#include <string>
#ifndef COMPLEX_H
#define COMPLEX_H
class Complex {
public:
double real;
double imaginary;
Complex();
Complex(const double real);
Complex(const double real, const double imaginary);
Complex(const Complex &rhs);
Complex& operator *= (const Complex&);
Complex& operator += (const Complex&);
Complex& operator /= (const Complex&);
Complex& operator -= (const Complex&);
Complex& operator = (const Complex&);
};
class Complex;
double abs(const Complex& c);
Complex operator * (const Complex& c1, const Complex& c2);
Complex operator / (const Complex& c1, const Complex& c2);
Complex operator + (const Complex& c1, const Complex& c2);
Complex operator - (const Complex& c1, const Complex& c2);
bool operator == (const Complex& c1, const Complex& c2);
bool operator != (const Complex& c1, const Complex& c2);
std::istream& operator >> (std::istream& in, Complex& c);
std::ostream& operator << (std::ostream& out, const Complex& c);
Complex operator ""_i(long double arg);
Complex operator ""_i(unsigned long long arg);
#endif
Upvotes: 1
Views: 119
Reputation: 15976
It's not really about member vs non-member. You returned references in your member functions because they actually modified this
value.
Consider the following code:
Complex c1, c2, c3;
// ...
(c3 *= c2) += c1;
Here c3 *= c2
will be evaluated, then operator+=
will be called on the result with c1
as parameter. If you return a copy instead of a reference for c3 *= c2
, the next applied operator+=
will modify this returned copy instead of c3
, which is not what one would expect.
Note that you could have declared your other operators as member functions as well, just to show the reference vs copy is not related to member vs non-member:
class Complex {
// ...
Complex& operator *= (const Complex&);
Complex& operator += (const Complex&);
Complex& operator /= (const Complex&);
Complex& operator -= (const Complex&);
Complex& operator = (const Complex&);
Complex operator * (const Complex& c2);
Complex operator / (const Complex& c2);
Complex operator + (const Complex& c2);
Complex operator - (const Complex& c2);
};
Upvotes: 2
Reputation: 1215
Just as those above me stated, the important question is not whether this is a member or non-member, but rather whether the returned value is a new instance or not.
Any operation that changes the object itself (like ++, +=, -=, ...) should return a reference to that same object. On the other hand, any operation that results in another object (like binary +, -, etc...) must create a new object, since the original operands should never be changed.
Moreover, you can have some binary operators be members (e.g., complex + int), while other must be defined outside the class (e.g., int + complex). Of course, you would like these two operations to behave identically.
Upvotes: 2
Reputation: 388
You have to look at what you'll expect from the result when you call your operator.
For example, if you use the operator*, you'll expect to have maybe
//Some Complex instances c1 and c2 already created
Complex c3 = c1 * c2;
You would not want to have c1 or c2 modified. So the copy here is nice.
But if you use the operator*=, you expect the result to modify your Complex instance on which the operator has been called on. So here, a reference is better because you'll avoid the copy constructor and destructor.
So the example you gave is ok.
Upvotes: 2