3

I have written a class for complex numbers in which I have overloaded the operator + and everything works fine, however I need to implement this as a non-member function and I am not sure how, or why there is a benefit of doing so.

Here is my code .h:

class Complex
{
private:
    double a;
    double b;

public:
    Complex();
    Complex(double aGiven);
    Complex(double aGiven, double bGiven);

    double aGetValue();
    double bGetValue();    
    double operator[](bool getB);

    Complex add(Complex &secondRational);
    Complex operator+(Complex &secondRational);
}

.cpp:

Complex Complex::add(Complex &secondRational)
{
    double c = secondRational.aGetValue();
    double d = secondRational.bGetValue();
    double anew = a+c;
    double bnew = b+d;
    return Complex(anew,bnew);
}

Complex Complex::operator+(Complex &secondRational)
{
    return add(secondRational);
}

Any help on how to make these as non-member functions will be greatly appreciated!

user906357
  • 4,575
  • 7
  • 28
  • 38
  • possible duplicate of [Operator overloading](http://stackoverflow.com/questions/4421706/operator-overloading) – Xeo Oct 09 '13 at 21:06
  • 1
    You do need to read about `const`. Very urgently. – sbi Oct 10 '13 at 17:44

4 Answers4

2

Here is the addition operator outside of the class:

Complex operator+(const Complex& lhs, const Complex& rhs) {
  //implement the math to add the two
  return Complex(lhs.aGetValue() + rhs.aGetValue(),
                 lhs.bGetValue() + rhs.bGetValue());
}

Of course you will need to declare aGetValue() and bGetValue() as const:

double aGetValue() const {return a;}
double bGetValue() const {return b;}
pippin1289
  • 4,861
  • 2
  • 22
  • 37
1

The usual approach to arithmetic operations is to define the reflexive versions of the operators as members and the pure versions as non-members, implementing them with the reflexive versions:

class complex {
public:
    const complex& operator+=(const complex& rhs) {
        real += rhs.real;
        imag += rhs.imag;
        return *this;
    }
};

complex operator+(const complex& lhs, const complex& rhs) {
    complex res(lhs);
    res += rhs;
    return res;
}
Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • @DanielFrey - I almost did that, but decided it was too confusing. – Pete Becker Oct 09 '13 at 20:20
  • 3
    Now you managed to confuse me. Why do you think it would be confusing? Considering `int i = 0; (i+=1)+=2;` is legal for integral types, why shouldn't it be legal for UDTs? – Daniel Frey Oct 09 '13 at 20:22
  • @DanielFrey - `(i+=1)+=2;` is confusing. `` `i += 1 + 2;` is much better. – Pete Becker Oct 09 '13 at 20:24
  • 1
    OK, can't argue with that :) (not that I will adopt this style, but I'll accept that other opinions are also possible in this case. Also: `i+=j+k` is not better for UDTs as it will create a temporary and thus it is less efficient). – Daniel Frey Oct 09 '13 at 20:24
  • @DanielFrey: are you saying that expressions `i + j + k` are now harder to optimize than if `+=` returned by non-const reference? Furthermore, I think "do as the ints do" is important in generic code, and should trump disallowing users to write obscure code. – TemplateRex Oct 09 '13 at 20:53
  • @DanielFrey - I'm not worried about an extra object of type `complex`. – Pete Becker Oct 09 '13 at 21:06
  • Sorry, but I have to downvote it because it is surprising for anyone writing a thin wrapper around a builtin that happens to use chained assignment (even though I agree that this is obscure code). If you want to promote a non-canonical version with the reference-to-const, I think it should be done as a comment or answer to the [canonical question](http://stackoverflow.com/q/4421706/819272). – TemplateRex Oct 09 '13 at 21:11
  • 3
    @TemplateRex Temporaries are no big deal if the objects are small, `Complex` here is just two doubles. But I used to work with `Complex` and `T` was a base-10 high-precision custom type. Or think of matrices. This is where it becomes important to avoid temporaries and why libraries like my df.operators try to avoid them. And this is also why you should IMHO allow users to write "stupid" stuff like `(i+=j)+=k;`. Yes, a sane person would use `i+=j; i+=k;`, but my experience says I can't assume sane behaviour from others at all time :-) – Daniel Frey Oct 09 '13 at 21:12
  • @DanielFrey I am thinking about large `std::bitset` objects, with complicated logical expressions. – TemplateRex Oct 09 '13 at 21:14
  • @TemplateRex Another good example where `i&=j; i|=k;` might be less efficient as the optimizer might not be able to go over the memory only once now compared to `(i&=j)|=k`. Obviously this is all mood without measuring it. Considering your downvote: You might balance it with Pete's answer being the only one that promotes `+` being implemented with `+=`. – Daniel Frey Oct 09 '13 at 21:17
  • @DanielFrey agreed on the `+=` but since this is like the quadruple dupe of the +500 Q&A, I think it should not have received any answer at al. – TemplateRex Oct 09 '13 at 21:20
  • @TemplateRex - so you're downvoting my answer because you think the question should have been closed as a duplicate? That makes no sense. – Pete Becker Oct 10 '13 at 11:35
  • 2
    @PeteBecker no the dupe was a side remark. I downvoted for the `const` ref because it's different from builtin behavior and standard libray practice, and quite possibly a performance pessimization. – TemplateRex Oct 10 '13 at 16:43
  • @TemplateRex - you can't see the forest for the trees. – Pete Becker Oct 10 '13 at 16:44
  • @PeteBecker sorry, how are such comments going to help me see what you deem so obvious? I gave 2 imho legitimate reasons for downvoting and you did not respond to either of them. – TemplateRex Oct 10 '13 at 17:12
  • 3
    `T x; T& y = (x += 1);` should be valid. Not because I want to use it, but because you do not have a good reason to prevent me from doing so. End of story! – Lightness Races in Orbit Oct 10 '13 at 17:34
  • 2
    _"Do as the ints do"_ is a very basic rule of operator overloading and [I happen to agree with that](http://stackoverflow.com/a/4421708/140719). This class' `operator+=()` violates that rule. – sbi Oct 10 '13 at 17:43
  • 2
    (+1 still a good answer, correct otherwise, and incidentally by far the best) – Lightness Races in Orbit Oct 10 '13 at 17:43
1

How is explained above by pippin1289.

Why is explained below:

Imagine one need to use object of class as

Complex c3 = 5 + c1;// for c3 object c1's real part (a) added with 5

As C++ preserve order of operand. Compiler resolve above addition call as 5.operator+ (const Complex & other);// which is not possible Hence, overload it via free function.

Your class is exposing necessary information via public interface such as aGetValue() and bGetValue. Hence, this free overloaded + operator function need not be friend of class.

Additionally, Prefer non friend non member function over member function as it helps reduce degree of encapsulation. This is explained here ==> http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197?pgno=1

sidd.rane
  • 11
  • 3
0

You can declare a friend to your Complex class

class Complex {

// blah....

    friend Complex operator+(Complex const& a, Complex const & b);
};

The overloaded operator can access the private members of Complex.

CS Pei
  • 10,869
  • 1
  • 27
  • 46