I have class Complex, with defined friend Complex operators of +,-,*,/.
class Complex
{
private:
float Re;
float Im;
public:
friend Complex operator + (const Complex ,const Complex );
friend Complex operator * (const Complex ,const Complex );
friend Complex operator - (const Complex ,const Complex );
friend Complex operator / (const Complex ,const Complex );
};
Complex operator + (const Complex a,const Complex b)
{
Complex c(0,0);
c.Re=a.Re+b.Re;
c.Im=a.Im+b.Im;
return c;
}
Complex operator * (const Complex a,const Complex b)
{
Complex c(0,0);
c.Re=a.Re*b.Re;
c.Im=a.Im*b.Im;
return c;
}
Complex operator - (const Complex a,const Complex b)
{
Complex c(0,0);
c.Re=a.Re-b.Re;
c.Im=a.Im-b.Im;
return c;
}
Complex operator / (const Complex a,const Complex b)
{
if(b.Im && b.Re)
{
Complex c(0,0);
c.Re=a.Re/b.Re;
c.Im=a.Im/b.Im;
return c;
}
else
{
std::cout<<"Cannot divide, one of parametars is zero."<<std::endl;
}
}
What i want to optimse is instead of writing this all this so many times, and just changing the +,-,*,/ operator, i could write it once, and when in int main()
some of operators is beigned called(used) just read it and apply it to the function. Is it possible?
You can do something like this:
Add this template function into Complex:
template <typename OP>
static Complex apply(const Complex a, const Complex b, OP op) {
Complex c;
c.Re = op(a.Re, b.Re);
c.Im = op(a.Im, b.Im);
return c;
}
Then the implementation of the operators is a little bit smaller:
Complex operator + (const Complex a,const Complex b)
{
return Complex::apply(a, b, std::plus<float>());
}
Complex operator * (const Complex a,const Complex b)
{
return Complex::apply(a, b, std::multiplies<float>());
}
Complex operator - (const Complex a,const Complex b)
{
return Complex::apply(a, b, std::minus<float>());
}
Complex operator / (const Complex a,const Complex b)
{
if(b.Im && b.Re)
{
return Complex::apply(a, b, std::divides<float>());
}
else
{
std::cout<<"Cannot divide, one of parametars is zero."<<std::endl;
// Note: missing return value here
}
}
Note: multiplication and division aren't defined like this for complex numbers.
Note2: I don't think this can be much smaller, as you must define the operators one by one, as far as I know (there is no trickery to define them at once, at least not in C++17).
Related
I am reading a textbook (of Bjarne Stroustrup) definition of class complex
class complex {
double re, im; // representation: two doubles
public:
complex(double r, double i) :re{r}, im{i} {} // construct complex from two scalars
complex(double r) :re{r}, im{0} {} // construct complex from one scalar
complex() :re{0}, im{0} {} // default complex: {0,0}
double real() const { return re; }
void ral(double d) { re = d; }
double imag() const { return im; }
void imag(double d) { im = d; }
complex& operator+=(complex z) { re+=z.re, im+=z.im; return *this; } // add to re and im
// and return the result
complex& operator-=(complex z) { re-=z.re, im-=z.im; return *this; }
complex& operator*=(complex); // defined out-of-class somewhere
complex& operator/=(complex); // defined out-of-class somewhere
};
The book also defines operations of complex:
complex operator+(complex a, complex b) { return a+=b; }
complex operator-(complex a, complex b) { return a-=b; }
complex operator-(complex a) { return {-a.real(), -a.imag()}; } // unary minus
complex operator*(complex a, complex b) { return a*=b; }
complex operator/(complex a, complex b) { return a/=b; }
I do not understand the third line above, which deals with unary minus. Why does it make sense to use an initializer list as the return value of operator-(complex a);?
You have to have
return {-a.real(), -a.imag()};
because you want to return a complex that is created from those two values. If you tried using
return -a.real(), -a.imag();
instead then you would return a complex that was created from just -a.imag() since the comma operator only returns the last value. Essentially, the code is exactly the same as
return -a.imag();
To make it more explicit, the author could have written
return complex{-a.real(), -a.imag()};
//or
return complex(-a.real(), -a.imag());
but that really isn't needed since the return value is always converted to the return type and with initializer lists, they are used like you had typed return_type{ initializers }.
Without the initializer list you have to write
complex operator-( complex a ) { return complex( -a.real(), -a.imag() ); }
With the initializer list the definition of the operator looks simpler.
In any case the compiler selects the constructor
complex( double, double );
Take into account that in general the function should be declared like
complex operator-( const complex &a ) { return { -a.real(), -a.imag() }; }
The return type of that function is a complex object, so those parameters in the intitializer list are inferred as parameters to complex constructor and a new object is returned.
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();
I have created class which represents line aX + bY = c and I wanted overload + operator to higher the line(return higher Line so I have done that below but compilator says invalid use of this
class Linia{
public:
double a,b,c;
Linia (double a, double b, double c){
this->a = a;
this->b = b;
this->c = c;
}
friend Linia operator+ (double i){
return new Linia(a, this->b, this->c + i/this->b);
}
};
I would like to return new Linia object which is has fields like shown above i is int i do not want to modify original object
You have some basic syntax issues.
this is a pointer so you need to use -> to dereference it.
I assume you mean this->c + i.c instead of this->c + i
You don't need to (and probably shouldn't) have the operator be a friend.
Operators that return a new instance (like operator+) should return by value, not allocate on the heap.
Operators generally take parameters as const references (since you shouldn't be modifying the operands).
I think you mean to have something like this:
class Linia{
public:
double a,b,c;
Linia (double a, double b, double c){
this->a = a;
this->b = b;
this->c = c;
}
Linia operator+ (const Linia& i){
return Linia(this->a, this->b, this->c + i.c / this->b);
}
};
which you can clean up to be something like this:
class Linia{
public:
double a,b,c;
Linia (double a, double b, double c)
: a(a), b(b), c(c)
{ }
Linia operator+ (const Linia& i){
return Linia(a, b, c + i.c / b);
}
};
There are at least two problems in your code. First, you've declared operator+ to be a friend, so it is a free function, with no this. Regretfully, from the code, I'm not able to figure out what you're trying to do (overload unary + or overload binary +), so it's difficult to say more. Second, you're trying to return the results of new, which is a pointer, not an object type. operator+ should always return an object type, so you don't want the new.
Assuming that your operator+ is a binary operator that takes two Linias as input and returns a Linea having added coefficients, you may want to define a free function operator+ overload, with proper const correctness of the input Linias, like this:
Linia operator+(const Linia& lhs, const Linia& rhs)
{
return Linia
(
lhs.a + rhs.a,
lhs.b + rhs.b,
lhs.c + rhs.c
);
}
Since you declared it as a friend, your addition operator is not a member function, hence it must take two parameters, and has no access to this:
friend Linia operator+ (const Linia& lhs, const Linia& rhs)
{
return Linia(lhs.a, lhs.b, lhs.c + rhs/lhs.b);
}
This follows the logic in your code but will only work if there is an operator double operator/(const Linia& lhs, double). Something that intuitively would make sense would be
friend Linia operator+ (const Linia& lhs, const Linia& rhs)
{
return Linia(lhs.a+rhs.a, lhs.b+rhs.b, lhs.c + rhs.c);
}
Finally, you could avoid the friend declaration completely and just declare the operator as a standard non-member function. It doesn't access any private or protected data, so it doesn't need to be a friend.
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.
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.