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;
}
Related
I write this code with a class named Complex with the following methods:
a. Complex() // Default constructor returning 0
b. Complex(float im, float real)
c. float getImaginary() const
d. float getReal() const
e. Complex add(const Complex& rhs) const
f. Complex subtract(const Complex& rhs) const
g. Complex multiply(const Complex& rhs) const
#include <iostream>
using namespace std;
class Complex {
private:
float real;
float imaginary;
public:
Complex();
Complex(float real=0, float im=0);
float GetReal() const;
float GetImaginary() const;
Complex Add(const Complex &rhs) const;
Complex Subtract(const Complex &rhs) const;
Complex Multiply(const Complex &rhs) const;
void SetReal(float r);
void SetImaginary(float i);
};
Complex::Complex()
{
real=imaginary=0;
}
Complex::Complex(float realpart, float imaginarypart)
{
SetReal(real);
SetImaginary(imaginarypart);
}
void Complex::SetReal(float r)
{
real = r;
}
void Complex::SetImaginary(float i)
{
imaginary = i;
}
float Complex::GetReal() const
{
return real;
}
float Complex::GetImaginary() const {
return imaginary;
}
Complex Complex::Add(const Complex &rhs) const {
return Complex(GetReal() + rhs.GetReal(), GetImaginary() + rhs.GetImaginary());
}
Complex operator+(const Complex &rhs1, const Complex &rhs2) {
return rhs1.Add(rhs2);
}
Complex Complex::Subtract(const Complex &rhs) const
{
return Complex(GetReal() - rhs.GetReal(), GetImaginary() - rhs.GetImaginary());
}
Complex operator-(const Complex &rhs1, const Complex &rhs2)
{
return rhs1.Subtract(rhs2);
}
Complex Complex::Multiply(const Complex &rhs) const
{
return Complex(GetReal() * rhs.GetReal(), GetImaginary() * rhs.GetImaginary());
}
Complex operator*(const Complex &rhs1, const Complex &rhs2)
{
return rhs1.Multiply(rhs2);
}
int main()
{
Complex c();
Complex x(-2,4);
Complex y(5,6);
Complex z = x + y;
cout << z.GetReal() << '+' << z.GetImaginary() << 'i' << endl;
Complex e = x - y;
cout << e.GetReal() << '+' << e.GetImaginary() << 'i' << endl;
Complex r = x * y;
cout << r.GetReal() << '*' << r.GetImaginary() << 'i' << endl;
return 0;
}
but i take these output
8.99944e-039+10i
8.99944e-039+-2i
8.99944e-039*24i
Can somebody help me for this error ?
3 issues in your code:
Complex::Complex(float realpart, float imaginarypart)
{
SetReal(realpart);
SetImaginary(imaginarypart);
}
causes the warning:
<source>:24:28: warning: unused parameter 'realpart' [-Wunused-parameter]
24 | Complex::Complex(float realpart, float imaginarypart)
|
Fix it by passing realpart to SetReal or rather use the member initializer list:
Complex::Complex(float realpart, float imaginarypart) : real(realpart),imaginary(imaginarypart)
{}
Next, this:
Complex c();
is the most vexing parse. It declares a function named c taking no parameters and retuning a Complex. It is not declaring a variable c of type Complex. Write
Complex c;
Complex c{};
to call the default constructor. However, you class has two default constructors:
Complex();
Complex(float real=0, float im=0);
A default constructor is one that can be called without parameters and thats the case for both of these. Hence you currently cannot default construct a Complex, the constructors are ambigoous. I read your assignemnt as requiring you to provide two constructors:
Complex();
Complex(float real, float im); // no defaults !!
Then you will be able to default construct a Complex via Complex c; or Complex c{}; (but not via Complex c(); because thats a function declaration).
After fixing those, I get almost reasonable looking output: https://godbolt.org/z/x4xG8xzTf
Finally, your formula for multipliying two complex numbers is wrong. I'll leave that for you to fix it.
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.
I have the following code where I need to add two complex numbers. Formula is working, however, I am not able to get rid of the scientific notation. I'm new to C++, and not sure how to use setPrecision.
My code in .hpp:
class ComplexNumber
{
public:
//--constructors
ComplexNumber();
ComplexNumber(double r, double i);
ComplexNumber(const ComplexNumber &cn);
void print();
ComplexNumber add(const ComplexNumber &rhs);
private:
double re, im;
};
My code in .cpp file
//--constructors
ComplexNumber::ComplexNumber()
{
}
ComplexNumber::ComplexNumber(double r, double i)
{
}
ComplexNumber::ComplexNumber(const ComplexNumber &cn)
{
}
void ComplexNumber::print()
{
std::cout << this->re << " + " << this->im << "i" << std::endl;
}
ComplexNumber ComplexNumber::add(const ComplexNumber &rhs)
{
return ComplexNumber(this-> re + rhs.re, this->im + rhs.im);
}
My main:
int main(int argc, const char * argv[]) {
ComplexNumber a(1,2);
ComplexNumber b(3,4);
ComplexNumber c;
c = a.add(b);
c.print();
return 0;
}
Output:
4.94066e-324 + 6.95322e-310i
it should be 4 + 6i
None of your constructors actually do anything. That means the member variables will be uninitialized, their values will be indeterminate and using them will lead to undefined behavior
You need to actually initialize the members in the constructors.
Works as expected after fixing the syntax (making it an aggregate):
#include <iostream>
struct ComplexNumber
{
void print();
ComplexNumber add(const ComplexNumber &rhs);
double re, im;
};
void ComplexNumber::print()
{
std::cout << this->re << " + " << this->im << "i" << std::endl;
}
ComplexNumber ComplexNumber::add(const ComplexNumber &rhs)
{
return ComplexNumber{this-> re + rhs.re, this->im + rhs.im};
}
int main(int argc, const char * argv[]) {
ComplexNumber a{1,2};
ComplexNumber b{3,4};
ComplexNumber c;
c = a.add(b);
c.print();
return 0;
}
Precision is not the issue here.
Your two-argument constructor needs to be implemented as follows
ComplexNumber::ComplexNumber(double r, double i) : re(r), im(i)
{
}
otherwise the class members stay uninitialised.
Reading uninitialised variables is undefined behaviour in C++; your output is a manifestation of that.
It's stylistically acceptable (and in my opinion preferable for a number class) to write
ComplexNumber() = default;
for your default constructor; if you want it to keep the class members uninitialised, as is the case for the C++ built-in types. Just don't read the member variables before assigning them to something.
Finally, rely on the compiler to generate the copy constructor for you: there's no need to build your own.
I have been trying to compile this program but it is giving me an error in regards to overloading the * operator for one of the functions: complex operator *(double n)const
When I try to compile I get the error: no match for 'operator*' in '2 * c'
Here is the header file:
Complex.h
#ifndef COMPLEX0_H
#define COMPLEX0_H
class complex {
double realNum;
double imagNum;
public:
complex();
complex(double x,double y);
complex operator *(double n)const;
complex operator *(const complex &c1)const;
friend std::istream &operator>>(std::istream &is,complex &cm);
friend std::ostream &operator<<(std::ostream &os,const complex &cm);
};
#endif
Here is the cpp:
Complex.cpp
#include "iostream"
#include "complex0.h"
complex::complex() {
imagNum = 0.0;
realNum = 0.0;
}
complex::complex(double x, double y) {
realNum = x;
imagNum = y;
}
complex complex::operator *(const complex& c1) const{
complex sum;
sum.realNum=realNum*c1.realNum-c1.imagNum*imagNum;
sum.imagNum=realNum*c1.imagNum+imagNum*c1.realNum;
return sum;
}
complex complex::operator *(double n)const{
complex sum;
sum.realNum=realNum*n;
sum.imagNum=imagNum*n;
return sum;
}
std::istream &operator >>(std::istream& is, complex& cm) {
is >> cm.realNum>> cm.imagNum;
return is;
}
std::ostream &operator <<(std::ostream& os, const complex& cm){
os<<"("<<cm.realNum<<","<<cm.imagNum<<"i)"<<"\n";
return os;
}
main.cpp
#include <iostream>
using namespace std;
#include "complex0.h"
int main() {
complex a(3.0, 4.0);
complex c;
cout << "Enter a complex number (q to quit):\n";
while (cin >> c) {
cout << "c is " << c << "\n";
cout << "a is " << a << "\n";
cout << "a * c" << a * c << "\n";
cout << "2 * c" << 2 * c << "\n";
cout << "Enter a complex number (q to quit):\n";
}
cout << "Done!\n";
return 0;
}
Can someone explain to me what I have done wrong?
The member function operator only applies when the first operand is of your class type. If you want to handle the case where the second operand is of your type, you need also a free function (in which we simply delegate to the member function by virtue of commutativity of the operation):
complex operator*(double n, complex const & x)
{
return x * n;
}
(Please note that the standard library already contains <complex>.)
You have a member function defined as follows:
complex complex::operator *(double n) const;
That will let you do things like: complex_number * 3.0, but not 3.0 * complex_number. However, you can't create a member function that will let you do 3.0 * complex_number. The only place you could create that member function, is inside the definition of double, which you can't change.
Instead of doing it as member functions though, you can also do it as free-standing functions:
complex operator*(complex x, double n); // Called for complex_number * 2.0
complex operator*(double n, complex x); // Called for 2.0 * complex_number
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.