operator overloading and non-member functions c++ - c++

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!

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;}

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;
}

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

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.

Related

how to overload + and += operators as non-member functions?

I'm currently trying to refresh and improve my C++ skills and I'm reading a few books in parallel depending on the subject I need to dig into.
I'm currently spending time on The C++ Programming Language from Stroustrup. At page 61/62, there's an example of class for Complex numbers. It overloads a number of operators like += and -=. At the same time, it says that "Many useful operations do not require direct access to the representation of complex, so they can be defined separately from the class definition".
Now, when I try the following code:
#pragma once
#include <iostream>
class Complex
{
private:
double re, im;
public:
Complex(double r, double i): re{r}, im{i} {}
Complex(double r): re{r}, im{0} {}
Complex(): re{0}, im{0} {}
double real() const { return re; }
void real(double d) { re = d; };
double imag() const { return im; }
void imag(double d) { im = d; }
void print();
Complex& operator+= (Complex z) { re += z.re, im += z.im; return *this; }
Complex& operator-= (Complex z) { re -= z.re, im -= z.im; return *this; }
};
Complex operator+ (Complex a, Complex b) { return a += b; }
I get a link error: class Complex_cdecl operator+(class Complex, class Complex) already defined in Complex.obj
One or more multiply defined symbols found.
So, I suppose the code presented in the book here is only partial. I can't figure out though what's the right way to overload both + and +=. Is the book wrong here or obsolete?
Thanks for your help.
In your example the operator + should either be made inline so that the linker knows that multiple obj files can contain the same function definition.
inline Complex operator+ (Complex a, Complex b) { return a += b; }
Or the header file should contain only the declaration
Complex operator+ (Complex a, Complex b);
and exactly one cpp file should contain the definition
Complex operator+ (Complex a, Complex b) { return a += b; }

Error while overloading operator +,-,*,/ in c++ [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 6 years ago.
I am getting error while trying to compile the following code. I am beginner. Please help me figuring it out. I am trying to overload the operators _,+,/,*. It shows error while compiling. Should I use "friend" to solve this?
#include<stdio.h>
class complex{
private:
double real; //real part of complex
double imag; // imaginary part of complex
public:
complex(double r=0., double i=0.):real(r),imag(i)
{
} // constructor with initialization
complex(const complex&c):real(c.real),imag(c.imag)
{
} // copy constructor with initialization
~complex()
{
} // destructor
double re() const
{
return real;
} // read real part
double im() const
{
return imag;
} // read imaginary part
const complex& operator=(const complex&c)
{
real=c.real;
imag=c.imag;
return *this;
} //assignment operator
const complex& operator+=(const complex&c)
{
real += c.real;
imag += c.imag;
return *this;
} // addition of current complex
const complex& operator-=(const complex&c)
{
real -= c.real;
imag -= c.imag;
return *this;
} // subtract from current complex
const complex& operator*=(const complex&c)
{
double keepreal = real;
real = real*c.real-imag*c.imag;
imag = keepreal*c.imag+imag*c.real;
return *this;
} // multiply current complex with a complex
const complex& operator/=(double d)
{
real /= d;
imag /= d;
return *this;
} // divide current complex with real
void print(const complex&c)
{
printf("(%f,%f)\n",c.re(),c.im() );
} // printing complex number
friend complex operator !(const complex& c)
{
return complex(c.re(),-c.im());
}
friend double abs2(const complex& c)
{
return c.re()*c.re()+c.im()*c.im();
} // absolute value of complex
const complex& operator/=(const complex&c)
{
return *this *= (!c)/=abs2(c);
} // divide the current complex by a complex
const complex operator-(const complex& c)
{
return complex(-c.re(),-c.im());
} // negative of complex number
const complex operator-(const complex& c,const complex& d)
{
return complex(c.re()-d.re(),c.im()-d.im());
} // difference between complex numbers
const complex operator+(const complex& c,const complex& d)
{
return complex(c.re()+d.re(),c.im()+d.im());
} // addition of complex numbers
const complex operator*(const complex& c,const complex& d)
{
return complex(c)*=d;
} // multiplication of complex numbers
const complex operator/(const complex& c,const complex& d)
{
return complex(c)/=d;
} // division of complex numbers
};
int main(){
complex c(1.,0.),d(3.,4.);
print(c-d);
print(c/d);
return 0;
}
the output I am getting is:
complex_nums.cpp:76:59: error: ‘const complex complex::operator-(const complex&, const complex&)’ must take either zero or one argument
const complex operator-(const complex& c,const complex& d)
^
complex_nums.cpp:80:59: error: ‘const complex complex::operator+(const complex&, const complex&)’ must take either zero or one argument
const complex operator+(const complex& c,const complex& d)
^
complex_nums.cpp:84:59: error: ‘const complex complex::operator*(const complex&, const complex&)’ must take either zero or one argument
const complex operator*(const complex& c,const complex& d)
^
complex_nums.cpp:88:59: error: ‘const complex complex::operator/(const complex&, const complex&)’ must take exactly one argument
const complex operator/(const complex& c,const complex& d)
^
complex_nums.cpp: In function ‘int main()’:
complex_nums.cpp:96:11: error: ‘print’ was not declared in this scope
print(c-d);
^
complex_nums.cpp:97:9: error: no match for ‘operator/’ (operand types are ‘complex’ and ‘complex’)
print(c/d);
All your operators (+,-,*,/) need exactly one or no arguments, unless they are friend functions. Mark all the operator functions as friend, and the code should work. Otherwise, eliminate 1 parameter from each of the operators, and instead of that use the current instance (this). Example for + operator with parameter removed:
const complex operator+(const complex& c)
{
return complex(c.re()+re(),c.im()+im());
}
Reference of friend arithmetic operators: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators-using-friend-functions/
Next Error
What are you doing with your print() function? It should be in global scope, because it takes a complex as parameter. Move print() out of the class into global scope, like this. If you still want to keep a print() for the object itself, do so, but the one for your class should look like below:
class complex
{
void print(const complex&c)
{
printf("(%f,%f)\n",re(),im() );
} // printing complex number
};
void print(const complex&c)
{
printf("(%f,%f)\n",c.re(),c.im() );
} // printing complex number
Binary operators are either free functions with 2 arguments (preferred) or member functions with one argument (not so good).
You have defined member functions with 2 arguments.
Turning them into free functions by adding friend is one way.
Another is to make them free functions, defined outside the class but written in terms of member functions (as you have done anyway):
struct complex
{
/* ... */
};
// class definition ends
//free function
inline complex operator/(const complex& c,const complex& d)
{
return complex(c)/=d;
} // division of complex numbers
Note, this function can be improved:
inline complex operator/(complex c,const complex& d)
{
c /= d;
return c;
}
Also, unary operators should return complex&, not const complex&. The thing you're returning is mutable, because you just mutated it.
For the errors with the operators must take either zero or one argument, this is because you are implementing the non-member function as a member funciton. These should be free functions to work properly, or should only take one argument and use this as the other.
See this question for clarification:
Operator overloading : member function vs. non-member function?
For the error with print, I guess you are trying to call the print member function. To do that you need to do e.g. the following:
complex(c-d).print();

Overloading operators outside of the class

So, i have a simple class:
class complex{
private:
double a,b;
public:
void setA(double a){ this->a=a; }
void setB(double b){ this->b=b; }
double getA(){ return a; }
double getB(){ return b; }
friend complex operator+(const complex&, const complex&);
};
And i have the actual overloaded operator here:
complex operator+(const complex& x, const complex& y){
complex c;
c.a=x.a+y.a;
c.b=x.b+y.b;
return c;
}
I must have the operator overloaded outside of the function. In order to have access to private variables (those also HAVE to be private) I befriended the class with the function. I don't know if that's correct way to do such things, but at least it works.
I want to be able to add an integer to both members. In main():
complex a;
a.setA(2);
a.setB(3);
a+5;
Would result in having a.a=7 and a.b=8. Such overload inside the class is quite easy to make (Again, don't know if that's good solution, if not please correct me):
complex operator+(int x){
this->a+=x;
this->b+=x;
}
But I have no idea how to make it outside of the class because i can't use "this" pointer.
The usual approach to this sort of problem is to have member functions that define the reflexive version of arithmetic operators and free functions that define the non-reflexive version, implemented with the reflexive version. No friend declarations needed. For example:
class complex {
public:
complex& operator+=(const complex& rhs) {
x += rhs.x;
y += rhs.y;
return *this;
}
private:
double x, y;
};
complex operator+(const complex& lhs, const complex& rhs) {
complex result = lhs;
result += rhs;
return result;
}
Having a+5 change the value of a is unusual, but if that's really wha you want, make operator+(int) a member. However, users would typically expect that a+5 would leave a unchanged, and that a += 5 would modify a.

How do I most efficiently return multiple values from an overloaded operator? (C++)

I have a class "complex" that contains a Real and an Imaginary value. I'm trying to overload the + operator so I can add real to real and imaginary to imaginary, but I'm banging my head against a wall here.
In the function, I can get the values easy. Returning them however, is a bitch.
My plan is to overload the '=' operator, too, so I can go
complex a, b, c;
(set a and b)
c = a + b;
then have a+b return a complex, then have complex c equal the complex returned by a+b
Any opinion on whether that's a viable path?
Any opinion on whether it can be done easier?
Return them as a complex! e.g.
const complex operator+(const complex &a, const complex &b)
{
return complex(a.re + b.re, a.im + b.im);
}
You shouldn't need to overload operator=; the compiler will generate one for you that does an element-by-element copy, which will probably suffice for a complex class.
I'm not sure I understand the problem. Do you have a complex class?
struct complex
{
complex(float real, float imag) :
real(real), imag(imag)
{}
// first make the mutating version
complex& operator+=(const complex& rhs)
{
real += rhs.real;
imag += rhs.imag;
return *this;
}
float real, imag;
};
// then use that for the non-mutating version
complex operator+(complex lhs, const complex& rhs)
{
lhs += rhs;
return lhs;
}
This is, of course, just an exercise; we have std::complex.
What's wrong with overloading the + operator:
complex operator+(const complex& a, const complex& b) const {
return complex(a.real + b.real, a.imag + b.imag);
}
And the operator=() similarly? (but the compiler give you this by default)
complex& operator=(const complex& a) {
real = a.real;
imag = a.imag;
return *this;
}
It is viable but there is already complex class in standard library. Reuse it or at least have a look how the operator overloading is done there.

Multiply a constant to a complex & operator overloading problems

Complex operator*(double m, const
Complex & c)
{ return c * m; }
*On the code above, i'm trying to multiply a constant to a complex number. i receive some errors one of them is [ binary 'operator ' has too many parameters]
ostream & operator<<(ostream & os,
Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
*****Can you tell me what i did wrong on this line as well.
Thanks*****
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double r, double i = 0);
Complex operator*(const Complex & c) const;
Complex operator*(double mult) const;
Complex operator*(double m, const Complex & c)
{ return c * m; }
ostream & operator<<(ostream & os, Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
};
Complex::Complex()
{
real = imaginary = 0;
}
Complex::Complex(double r, double i )
{
real = r;
imaginary = i;
}
Complex Complex::operator*(const Complex & c) const
{
Complex mult;
mult.imaginary = imaginary * c.imaginary;
mult.real = real * c.real;
return mult;
}
Complex Complex::operator*(double mult) const
{
Complex result;
result.real = real * mult;
result.imaginary = imaginary * mult;
return result;
}
int main()
{
Complex B(5, 40);
Complex C(6, 15);
cout << "B, and C:\n";
cout << B << ": " << C << endl;
cout << "B * C: " << B*C << endl;
cout << "10 * B: " << 10*B << endl;
return 0;
}
These two operators have problems:
class Complex {
// ...
Complex operator*(double m, const Complex & c)
{return c * m;}
ostream & operator<<(ostream & os, Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
Before anything else: That operator<< isn't supposed to change the complex outputs, so that should be const. (Otherwise you cannot output temporary objects, as they can't be bound to non-const references.)
Since they are non-static member functions, they have an implicit this parameter. With that, they have three parameters. However, both are binary operators. Since you cannot make them static (that's just because the rules say so), you have to implement them as free functions. However, as they are implemented, they need access to private members, so you would have to make them friends of your class:
class Complex {
// ...
friend Complex operator*(double m, const Complex & c);
friend ostream & operator<<(ostream & os, const Complex & c);
// ...
};
Complex operator*(double m, const Complex & c)
{return c * m;}
ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
On a sidenote, it's possible to implement them inline at the point of the friend declaration, which brings you back almost to your original version:
// note the friend
class Complex {
// ...
friend Complex operator*(double m, const Complex & c)
{return c * m;}
friend ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
However, if you implement a concrete mathematical type, your type's users will expect all operations common for such types to work with it. That is, they will, for example, expect c*=r to simply work. So you will need to overload operator*=, too. But that operator does almost the same as operator*, so it would be a good idea to implement one on top of the other. A common idiom is to implement *= (and += etc.) as member functions (since they change their left argument, it's a good idea for them to have access to its private data) and operator* as non-member on top of that. (Usually that's more efficient then the other way around.):
// note the friend
class Complex {
// ...
Complex& operator*=(double rhs)
{return /* whatever */;}
friend ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
inline Complex operator*(Complex lhs, double rhs) // note: lhs passed per copy
{return lhs*=rhs;}
inline Complex operator*(double lhs, const Complex& rhs)
{return rhs*lhs;}
IMO that's the best solution.
I have. however, a few more things to say:
The way you implemented your multiplication is inefficient:
Complex Complex::operator*(const Complex & c) const
{
Complex mult;
mult.imaginary = imaginary * c.imaginary;
mult.real = real * c.real;
return mult;
}
When you say Complex mult;, you invoke the default constructor of your class, which initializes the real and imaginary parts to 0. The next thing you do is to overwrite that value. Why not do it in one step:
Complex Complex::operator*(const Complex & c) const
{
Complex mult(real * c.real, imaginary * c.imaginary);
return mult;
}
or even to more concise
Complex Complex::operator*(const Complex & c) const
{
return Complex(real * c.real, imaginary * c.imaginary);
}
Sure, it's just two assignments per multiplication. But then - you wouldn't want to have this in some inner loop of your graphic driver.
Also, your constructors are not implemented The Way It Ought To be(TM). For initializing member data, you should use the initializer list:
Complex::Complex()
: real(), imaginary()
{
}
Complex::Complex(double r, double i)
: real(r), imaginary(i)
{
}
While it doesn't make any difference for built-in types like double, it doesn't hurt either and it's good to not to get into the habit. With user-defined types (a somewhat unfortunate name, since it is for all non-built-ins, even types like std::string, which isn't defined by users) that have a non-trivial default constructor, it does make a difference: it's far less efficient.
The reason is that, when the execution passes that initial {, C++ guarantees that your data member objects are accessible and usable. For that, they must be constructed, because construction is what turns raw memory into objects. So even if you do not call a constructor explicitly, the run-time system will still call the default constructors. If the next thing you do is overriding the default-constructed values, you're again wasting CPU cycles.
Finally, this constructor Complex(double r, double i = 0) serves as an implicit conversion operator. That is, if, for example, youe meant to call f(real), but forgot to include it, but there is an f(const complex&) in scope, the compiler exercises its right to perform one user-defined conversion and your call f(4.2) becomes f(Complex(4.2)) and the wrong function is silently called. That's very dangerous.
In order to avoid this, you should mark all constructors explicit that could be called with only one argument:
class Complex {
// ...
explicit Complex(double r, double i = 0)
// ...
};
Don't declare Complex operator*(double m, const Complex & c) and the ostream one as member functions (aka methods): declare them as friend functions instead! (If you even need them to be friends, which you wouldn't if you had the obvious inline accessor methods for the imaginary and real parts -- but anyway the point is that they have to be outside the class!).
For member functions, operator* and operator<< only take a single parameter, as the Complex object is already implicitly given, i.e.
c * r
translates to
c.operator*(r)
If you wish to have the two argument form, then an external friend function is what you are looking for. Although, as Alex points out, if you have re and im acessors set up, then your external operators need not be friends.