I'm writing a header file to learn more about operator overloading in C++, and I got the following error while implementing the division method for two complex numbers.
Here is the source code:
#ifndef __COMP_H
#define __COMP_H
#include <iostream>
class Complex{
private:
double real;
double imag;
public:
//constructor
Complex(double r=0, double i=0){real = r; imag = i;}
//operator overloading
Complex operator + (Complex const &obj){
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
Complex operator - (Complex const &obj){
Complex res;
res.real = real - obj.real;
res.imag = imag - obj.imag;
return res;
}
Complex operator * (Complex const &obj){
Complex res;
res.real = real*obj.real + (-1)*imag*obj.imag;
res.imag = real*obj.imag + imag*obj.real;
return res;
}
Complex operator * (double const i){
Complex res;
res.real = i*real;
res.imag = i*imag;
return res;
}
Complex operator / (Complex const &obj){
Complex conj(obj.real, (-1)*obj.imag);
Complex res = (*this)*obj; //numerator
Complex den = obj*conj; //denominator, it will be 0 as it's imaginary value
res = res*(1/den.real); //multiply it with a scalar value
return res;
}
void print(){
std::cout << real << " + " << imag << "j\n";
}
};
#endif
and the error looks as follows
In file included from main.cpp:2:
comp.h: In member function 'Complex Complex::operator/(const Complex&)':
comp.h:52:27: error: passing 'const Complex' as 'this' argument discards qualifiers [-fpermissive]
Complex den = obj*conj; //denominator, it will be 0 as it's imaginary value
^~~~
comp.h:32:13: note: in call to 'Complex Complex::operator*(const Complex&)'
Complex operator * (Complex const &obj){
^~~~~~~~
I've seen other answers on stackoverflow but did not understand it, what is meant by this error and how to fix it? Thanks!
This
Complex operator - (Complex const &obj) { ...
and others are non-const member functions. Member functions are non-const by default, meaning they are declared to modify this. You cannot call them on a const instance. Most of your operators do not modify this, hence should be declared as const:
Complex operator - (Complex const &obj) const { ...
// ^^
Related
This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
How to overload operator+
(3 answers)
Closed 2 years ago.
I am learning about overloading operators in c++ and I have done this code aboout the sum of two imaginary numbers, formed by the real part and the imaginary part.
#include<iostream>
using namespace std;
class Complex {
private:
int real, imag;
public:
Complex(int r, int i) {
real = r;
imag = i;
}
Complex operator + (Complex const &num1, Complex const &num2) {
Complex res;
res.real = num1.real + num2.real;
res.imag = num1.imag + num2.imag;
return res;
}
void print() {
cout << real << " + i" << imag << endl;
}
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2;
c3.print();
}
Something should be wrong because it shows a lot of errors, notes and warnings :(
error: ‘Complex Complex::operator+(const Complex&, const Complex&)’ must take either zero or one argument
error: no match for ‘operator+’ (operand types are ‘Complex’ and ‘Complex’)
note: ‘Complex’ is not derived from ‘std::__cxx11::basic_string<_CharT, _Traits, _Alloc>’
A binary (2 parameter) operator can't be a class member, it needs to be a standalone function instead:
class Complex {
...
public:
...
friend Complex operator + (Complex const &lhs, Complex const &rhs);
...
};
Complex operator + (Complex const &lhs, Complex const &rhs) {
return Complex(
lhs.real + rhs.real,
lhs.imag + rhs.imag
);
}
Which can also be inlined:
class Complex {
...
public:
...
friend Complex operator + (Complex const &lhs, Complex const &rhs) {
return Complex(
lhs.real + rhs.real,
lhs.imag + rhs.imag
);
}
...
};
So, a statement like c1 + c2 gets processed as operator+(c1, c2).
A unary (1 parameter) operator, on the other hand, must be a class member that acts on this as the left-side value:
class Complex {
...
public:
...
Complex operator + (Complex const &rhs) const {
return Complex(
real + rhs.real,
imag + rhs.imag
);
}
...
};
Then a statement like c1 + c2 gets processed as c1.operator+(c2).
The way you have defined operator+ is fine, expect that it needs to be a friend function. Also, note that Complex res; will not compile because you don't have a default constructor.
You could define the function like this:
friend Complex operator + (Complex const &num1, Complex const &num2) {
return {num1.real + num2.real, num1.imag + num2.imag};
}
Here's a demo.
Note also, that I fixed the bug where you are adding the imaginary part of num1 twice.
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();
When I try to over load an operator "!", it gives error as following.
complex_nums.cpp: In function ‘complex operator!(const complex&)’:
complex_nums.cpp:50:23: error: passing ‘const complex’ as ‘this’ argument discards qualifiers [-fpermissive]
return complex(c.re(),-c.im());
^
complex_nums.cpp:14:9: note: in call to ‘double complex::re()’
double re(){
^
complex_nums.cpp:50:31: error: passing ‘const complex’ as ‘this’ argument discards qualifiers [-fpermissive]
return complex(c.re(),-c.im());
^
complex_nums.cpp:17:9: note: in call to ‘double complex::im()’
double im(){
^
The code is:
#include<iostream>
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(){
return real;
}; // read real part
double im(){
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(){
std::cout<<"Real: "<<re()<<" Imaginary: "<<im()<<"\n";
};
friend complex operator !(const complex& c){
return complex(c.re(),-c.im());
};
};
int main(){
complex C(1.,1.);
complex P(3.,2.);
C.print();
P.print();
P+=C;
P.print();
P=!C;
P.print();
return 0;
}
This is the clue...
error: passing ‘const complex’ as ‘this’ argument discards qualifiers
The problem is that im() and re() are not const methods.
Declare these functions with the qualifier const
double re() const {
return real;
}; // read real part
double im() const {
return imag;
}; // read imaginary part
because at least in the operator
friend complex operator !(const complex& c){
return complex(c.re(),-c.im());
};
they are called for a constant object.
This is rule that when you create const function , function which is passed to this const function, must be also const.. re() and im() must be const
I've been making a class called Complex for storing and working with complex numbers. I'm having issues where my overloaded + and * functions return an obscenely large number, which I can only presume has something to do with pointers, but I'm very new to using them. I've copied the output here:
c1: 1 - i5
c2: -4 + i3
c1 + c2: -9.25596e+061 - i9.255
c1 * c2: -9.25596e+061 - i9.255
Press any key to continue . . .
Here is the class architecture:
// Complex.h
#include <iostream>
#include <cmath>
using namespace std;
class Complex
{
friend std::ostream &operator<<(std::ostream &, const Complex &);
friend std::istream &operator>>(std::istream &, Complex &);
friend Complex &operator+(const Complex &, const Complex &);
friend Complex &operator+(const Complex &, const double &);
friend Complex &operator+(const double &, const Complex &);
friend Complex &operator*(const Complex &, const Complex &);
friend Complex &operator*(const Complex &, const double &);
friend Complex &operator*(const double &, const Complex &);
public:
explicit Complex(double re=0, double im=0);
void setReal(double re);
void setImag(double im);
double &getReal();
double &getImag();
~Complex();
private:
double real;
double imag;
};
And here I have the relevant portions of my program:
// Complex.cpp
#include "Complex.h"
ostream &operator<<(ostream &output, const Complex &num)
{
output << num.real << (num.imag >= 0 ? " + i" : " - i") << abs(num.imag);
return output;
}
Complex &operator+(const Complex &num1, const Complex &num2)
{
Complex sum(num1.real + num2.real, num1.imag + num2.imag); // Create new complex by summing elements
return sum;
}
Complex &operator*(const Complex &num1, const Complex &num2)
{
Complex prod(num1.real * num2.real - num1.imag * num2.imag, num1.real * num2.imag + num1.imag * num2.real); // Create new complex by expansion
return prod;
}
Complex::Complex(double re, double im)
{
real = re;
imag = im;
}
int main() {
Complex c1(1.0, -5.0);
Complex c2(-4.0, 3.0);
cout << "c1: " << c1 << endl;
cout << "c2: " << c2 << endl;
cout << "c1 + c2: " << c1 + c2 << endl;
cout << "c1 * c2: " << c1 * c2 << endl;
system("pause");
}
I feel bad bothering you guys about this. Do you possibly know of a site that does a good job of explaining concepts for C++ like pointers, least-privilege, polymorphism, inheritance, etc?
Sorry for asking basic questions on here, but it's hard to find resources that explain this stuff clearly.
Wrong return type:
Complex &operator+(const Complex &num1, const Complex &num2)
^^^^^^^^^
You're creating a temporary Complex and returning it by reference, and then it gets destroyed so you have a dangling reference. Since operator+ is constructing a new object and returning it, it should return it by value... so the signature should be:
Complex operator+(Complex const&, Complex const& );
The problem is that most of your overloaded operators return a reference to a local var, which is destroyed when the operator function returns, leaving you with a dangling reference. Try changing your operators to return a Complex rather than a Complex &:
Complex operator+(const Complex &num1, const Complex &num2)
{
Complex sum(num1.real + num2.real, num1.imag + num2.imag); // Create new complex by summing elements
return sum;
}
Here's the current code:
const complex complex::operator+(const complex &right)
{
complex result;
result.realPart = realPart + right.realPart;
result.imPart = imPart + right.imPart;
return result;
}
How do i modify so that
a = b + c + d;
is allowed?
Make it a const member function:
const complex complex::operator+(const complex &right) const ...