Addition of complex numbers using classes - c++

I am trying to add 2 complex numbers together, but i am getting the errors:
no operator "+" matches these operands
no operator "<<" matches these operands
#include <iostream>
using namespace std;
class complex
{
public:
double get_r() { return r; }
void set_r(double newr) { r=newr; }
double set_i() { return i; }
void set_i(double newi) { i = newi; }
private:
double r, i;
};
int main()
{
complex A, B;
A.set_r(1.0);
A.set_i(2.0);
B.set_r(3.0);
B.set_i(2.0);
complex sum = A+B;
cout << "summen er: " << sum << endl;
system("PAUSE");
return 0;
};
I'm very new to programming, but i can't see why it won't add these numbers together. What have I done wrong?

You must overload operators + and << (and each one in your need) for your defined classes. Note that operators are no more than specific functions with specific definition syntax (operator+, for example: C = A + B could be understood as C = A.sum(B)). Here a link about http://en.cppreference.com/w/cpp/language/operators

Operator + is defined for builtin types and for some types from the standard library. As complex is here a custom class, you must define all operators that should act on it.
operator + could be defined as:
class complex {
...
complex operator + (const complex& other) {
return complex(get_r() + other.get_r(), get_i() + other.get_i());
}
...
};
Beware that does allow neither A++ nor A-B. They would require (resp.) complex & operator ++() or complex operator - (const complex &).
For stream insertion, the first parameter is the stream itself, so you must define a friend operator with 2 parameters outside the class:
outstream& opererator << (outstream &out, const complex& val) {
// output it the way you want
return out;
}

Complex numbers are part of the C++ standard. Here is the example from http://en.cppreference.com/w/cpp/numeric/complex.
#include <iostream>
#include <iomanip>
#include <complex>
#include <cmath>
int main()
{
using namespace std::complex_literals;
std::cout << std::fixed << std::setprecision(1);
std::complex<double> z1 = 1i * 1i;
std::cout << "i * i = " << z1 << '\n';
std::complex<double> z2 = std::pow(1i, 2);
std::cout << "pow(i, 2) = " << z2 << '\n';
double PI = std::acos(-1);
std::complex<double> z3 = std::exp(1i * PI);
std::cout << "exp(i * pi) = " << z3 << '\n';
std::complex<double> z4 = 1. + 2i, z5 = 1. - 2i;
std::cout << "(1+2i)*(1-2i) = " << z4*z5 << '\n';
}
Trying to implement a class complex yourself would require you define addition, equality, and ostream. And you would only have 5% of a fully implemented class. Looking at the header itself will reveal how those that wrote the C++ standard library implemented the whole thing.

All the arithmetic operators like plus, minus, multiply or divide only work with pre defined data types, like int, char, float etc.
Now if you want to add something in a class, you have to use the fundamental aspect of OO programming that is operator overloading.
Here is how you can achieve it.
#include <iostream>
using namespace std;
class complex
{
float x, y;
public:
complex()
{
}
complex(float real, float img)
{
x = real;
y = img;
}
friend complex operator+(complex,complex);
void display(void);
};
complex operator+(complex c,complex d)
{
complex t;
t.x = d.x + c.x;
t.y = d.y + t.y;
return(t);
};
void complex::display(void)
{
cout << x << "+i" << y << endl;
}
int main()
{
complex c1, c2, c3;
c1 = complex(2.5, 3.5);
c2 = complex(1.5, 5.5);
c3 = c1 + c2;//c3=opra+(c1,c2)
cout << "C1:" << endl;
c1.display();
cout << "C2:" << endl;
c2.display();
cout << "C3:" << endl;
c3.display();
}

Related

Copy Constructor called unexpectedly

I am new to C++ programming. I am using Visual Studio Code, my code:
#include <iostream>
using namespace std;
class Calculator;
class Complex
{
float a, b;
string Operation;
string name;
friend class Calculator;
public:
Complex(float, float, string, string);
Complex(float);
Complex();
Complex(Complex &, string);
void PrintComp(string op = "None")
{
if (op != "None" && name != "None")
{
cout << "\nBy " << op << " of z1 and z2:\n"
<< name << " = " << a << " + " << b << "i\n";
}
else if (name != "None")
{
cout << name << " = " << a << " + " << b << "i\n";
}
else
{
cout << a << " + " << b << "i\n";
}
}
};
Complex ::Complex(float x, float y, string givnname = "None", string operation = "None")
{
a = x;
b = y;
name = givnname;
PrintComp(operation);
}
Complex ::Complex(float x)
{
a = x;
b = 0;
}
Complex ::Complex()
{
a = 0;
b = 0;
}
Complex::Complex(Complex &obj, string givnname="None")
{
a = obj.a;
b = obj.b;
name = givnname;
cout << "Copy Cons called!"<< endl;
PrintComp();
}
class Calculator
{
public:
float SumRealComp(Complex const&, Complex const&);
float SumImgComp(Complex const&, Complex const&);
};
float Calculator ::SumRealComp(Complex const &obj1, Complex const & obj2)
{
return (obj1.a + obj2.a);
}
float Calculator ::SumImgComp(Complex const & obj1, Complex const & obj2)
{
return (obj1.b + obj2.b);
}
int main()
{
Complex z1(3, 5, "z1"), z2(4, 4, "z2");
Calculator calc;
Complex z3(calc.SumRealComp(z1, z2), calc.SumImgComp(z1, z2), "z3", "Sum");
Complex z4(z1, "z4");
return 0;
}
According to above code, I am using copy Constructor at the last, but
Copy Constructor is called at formation of every object. Even when args of both are different. Why it is so?
I am learning from here.
Every suggestions in my code are appreciated.
Thanks!
You will take a copy of Complex object on those functions:
Calculator::SumRealComp(Complex, Complex);
Calculator::SumImgComp(Complex, Complex);
So, on every call to those functions, you take two copies of the Complex object. You could pass a Complex const& object to avoid copy:
Calculator::SumRealComp(Complex const&, Complex const&);
Calculator::SumImgComp(Complex const&, Complex const&);
Copy Constructor
A copy constructor is one of the Class Special Member Functions, And called whenever we try to take a copy of the object:
class X;
void f(X);
X x;
f(x); // <--- Here
X another(x); // <--- Here
X yet_another = x; // <--- And here
In the commented sections we could call the X copy constructor. A copy constructor could be defined as the following signatures:
X::X(X&);
X::X(X const&);
X::X(X volatile&);
X::X(X const volatile&);
Note: Like your code, we could add additional parameters to the copy constructor while they have a default value).
Note: For more information: Read Chapter 17 of "The C++ Programming Language" by Bjarne Stroustrup.
This is not related to your question and are my suggestions to your code, If you don't like it you could skipped(or edit it and remove it)
Some Code Review Suggestions:
Stop using using namespace std; which could cause Undefined Behavior and give you a hard debugging time: Why is "using namespace std;" considered bad practice?
Don't complicate the Copy Constructor signature if not necessary. You could rewrite the copy constructor as follow:
Complex::Complex(Complex const& obj)
: a(obj.a)
, b(obj.b)
, name(obj.name)
{
cout << "Copy Cons called!" << endl;
PrintComp();
}
Initialize member variables using Member Initialize List.

Class does not name a type error even when class header file included in C++?

This occurs for my first member function for the class 'complex_test' (the constructor) so I assume I'm getting the same error for the rest of the functions.
FULL ERROR:error: 'complex_test' does not name a type.
The class implementation file below:
#include <fstream> // For ifstream, ofstream classes
#include "Complex.hpp" // For complex class declaration
#include "ComplexTest.hpp" // For complex_test class declaration
complex_test::complex_test()
{
}
void complex_test::run()
{
std::ifstream fin("complex-in.txt");
std::ofstream fout("complex-out.txt");
int n; fin >> n;
for (int testcase = 0; testcase < n; ++testcase) {
run_test(fin, fout);
}
// Close the input and output files.
fin.close();
fout.close();
}
void complex_test::run_test(ifstream& fin, ofstream& fout)
{
// Read the four double values.
double real1, imag1, real2, imag2;
fin >> real1 >> imag1 >> real2 >> imag2;
complex c1(real1, imag1);
complex c2(real2, imag2);
complex sum = c1.add(c2);
complex diff = c1.sub(c2);
complex product = c1.mul(c2);
complex quotient = c1.div(c2);
fout << "c1 = " << c1.to_string() << ", c2 = " << c2.to_string() << std::endl;
fout << "c1 + c2 = " << sum.to_string() << std::endl;
fout << "c1 - c2 = " << diff.to_string() << std::endl;
fout << "c1 * c2 = " << product.to_string() << std::endl;
fout << "c1 / c2 = " << quotient.to_string() << std::endl;
}
The class header for complex_test class:
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
#include <fstream>
using namespace std;
class complex_test {
public:
complex_test();
void run();
private:
void run_test(ifstream& fin, ofstream& fout);
};
#endif
In addition to this I get an error in the function implementation for the class 'complex' in line 62 for the get_real(), the compiler says it is not in scope, yet I defined it in the very same file?
Exact wording of error: 'get_real' was not declared in this scope.
#include <iomanip> // For fixed, setprecision()
#include <sstream> // For stringstream class
#include "Complex.hpp" // For the complex class declaration
#include <cmath>
complex::complex()
{
init(0,0);
}
complex::complex(double init_real, double init_imag)
{
init(init_real, init_imag);
}
double complex::get_imag()
{
return m_imag;
}
double complex::get_real()
{
return m_real;
}
void complex::init(double init_real, double init_imag)
{
m_real = init_real;
m_imag = init_imag;
}
void complex::set_imag(double s)
{
m_imag = s;
}
void complex::set_real(double s)
{
m_real = s;
}
std::string complex::to_string()
{
std::stringstream sout;
sout << std::fixed << std::setprecision(4);
sout << "(" << get_real();
double imag = get_imag();
if (imag < 0) {
sout << " - " << -imag << 'i';
} else if (imag > 0) {
sout << " + " << imag << 'i';
}
sout << ")";
return sout.str();
}
complex complex::add(complex& rhs_op)
{
double sum_real = get_real() + rhs_op.get_real();
double sum_imag = get_imag() + rhs_op.get_imag();
complex sum(sum_real, sum_imag);
return sum;
}
complex complex::div(complex& rhs_op)
{
complex inverse = rhs_op.invert();
complex quotient = mul(inverse);
return quotient;
}
complex invert()
{
double denom = std::pow(get_real(), 2) + std::pow(get_imag(), 2);
double inv_real = get_real() / denom;
double inv_imag = get_imag() / denom;
complex inverse(inv_real, inv_imag);
return inverse;
}
complex complex::mul(complex& rhs_op)
{
double prob_real = get_real() * rhs_op.get_real() - (get_imag() * rhs_op.get_imag());
double prod_imag = get_imag() * rhs_op.get_real() + (get_real * rhs_op.get_imag());
complex product(prod_real, prod_imag);
return product;
}
complex complex::negate()
{
complex neg(-get_real, -get_imag);
return neg;
}
complex complex::sub(complex& rhs_op)
{
complex negation = rhs_op.negate();
complex diff = add(negation);
return diff;
}
The header file for class 'complex':
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
#include <string>
class complex
{
public:
complex();
complex(double,double);
complex add(complex&);
complex div(complex&);
complex invert();
complex mul(complex&);
complex negate();
complex sub(complex&);
double get_imag();
double get_real();
void set_imag(double);
void set_real(double);
std::string to_string();
private:
void init(double , double );
double m_real;
double m_imag;
};
#endif
The first two lines of both of the shown header files appear to be:
#ifndef COMPLEX_HPP
#define COMPLEX_HPP
Which means that including either header file will make subsequent inclusion of the other header file a big fat nothing.
P.S. You will also remove more possibilities of other mysterious compilation errors by immediately forgetting that "using namespace std;" is a part of the C++ language. Do yourself a favor and completely get rid of it, especially in header files. It will take a little bit of time getting used it to it, but explicitly referencing the std namespace every time it's needed will quickly become second nature, and mostly an automatic, subconscious process, very quickly.

How can I have both conversion constructor and conversion operator?

Consider this simple C++-17 program:
#include <iostream>
#include <math.h>
using namespace std;
class Fraction {
public:
int nom;
int den;
Fraction operator+ (const Fraction& other) {
int nn = nom * other.den +
den * other.nom;
int dd = den * other.den;
return Fraction(nn, dd);
}
Fraction(int nn, int dn): nom(nn), den(dn) { }
Fraction(int nn): nom(nn), den(1) { }
operator double() const { return double(nom) / den; }
};
ostream& operator<<(ostream& os, const Fraction& frac) {
return os << frac.nom << '/' << frac.den;
}
int main() {
Fraction f1(1, 4);
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
return 0;
}
This program yields a compilation error:
main.cpp:35:52: error: use of overloaded operator '+' is ambiguous (with operand types 'Fraction' and 'int')
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
~~ ^ ~
main.cpp:17:11: note: candidate function
Fraction operator+ (const Fraction& other) {
^
main.cpp:35:52: note: built-in candidate operator+(double, int)
cout << "f1 = " << f1 << endl << "f1+2 = " << (f1 + 2) << endl;
^
However, if I remove either the conversion constructor "Fraction(int nn): nom(nn), den(1) { }" or the conversion operator "operator double() const { return double(nom) / den; }", the program runs fine.
I want to convert both to and from Fraction. What can I do to have both conversions and still have the program compile?
From the error, the compiler is complaining as it can't resolve the ambiguity on its own. As it correctly points out there are 2 possible solutions and it doesn't know which one to pick without additional insight from you.
How would you like (f1 + 2) evaluated, if you want Fraction addition, recommend changing caller to (f1 + Fraction(2)).
If you instead want double addition, change it to (double(f1)+2).
Bottom line, you can continue to have both conversion from fraction to double & integer to fraction construction, but you will need to explicitly specify the behavior you want when there is ambiguity for the compiler.
Make one or both conversion functions explicit. That will prevent your friendly compiler from implicitly using them when choosing an overload of operator + based on implicit conversions sequences.
explicit Fraction(int nn): nom(nn), den(1) { }
explicit operator double() const { return double(nom) / den; }
Just bear in mind it prevents all uses of those functions for implicit conversions.

Error while adding Complex numbers

In below program I am getting 2 errors at below lines.
r = sum(p,q); //Function sum should have a prototype.
r = sum(p,q); //Cannot convert int to complex
Kindly advise the changes in the code.
Note: I have to do the code by passing objects of complex class to add and also the addition should return a complex number.
#include<iostream.h>
#include<conio.h>
class Complex
{
private:
int real;
int imag;
public:
void getNo()
{
cout<<"Enter real part : "<<endl;
cin>>real;
cout<<"Enter imaginary part : "<<endl;
cin>>imag;
}
void showNo()
{
cout<<real<<"+"<<imag<<"i";
}
Complex sum(Complex, Complex);
};
Complex Complex :: sum(Complex c1, Complex c2)
{
Complex a;
a.real = c1.real + c2.real;
a.imag = c1.imag + c2.imag;
return a;
}
void main()
{
clrscr();
Complex p,q,r,s;
p.getNo();
q.getNo();
cout<<endl<<"First complex number is : ";
p.showNo();
cout<<endl<<"Second complex number is : ";
q.showNo();
r = sum(p,q);
cout<<"Addtion of the complex no is : ";
r.showNo();
getch();
}
For your purpose the "sum" function should not be in the "Complex" class. Here a bit changed code:
#include <iostream>
#include <conio.h>
using namespace std;
class Complex
{
public:
int real;
int imag;
void getNo ()
{
cout << "Enter real part : " << endl;
cin >> real;
cout << "Enter imaginary part : " << endl;
cin >> imag;
}
void showNo ()
{
cout << real << "+" << imag << "i";
}
};
Complex sum (Complex c1, Complex c2);
int main ()
{
//clrscr ();
Complex p, q, r, s;
p.getNo ();
q.getNo ();
cout << endl << "First complex number is : ";
p.showNo ();
cout << endl << "Second complex number is : ";
q.showNo ();
r = sum (p, q);
cout << endl << "Addtion of the complex no is : ";
r.showNo ();
getch ();
}
Complex sum (Complex c1, Complex c2)
{
Complex
a;
a.real = c1.real + c2.real;
a.imag = c1.imag + c2.imag;
return a;
}
Edit
Functions in class require an instance (object) of class.
Simply you CAN do this:
p.getNo();
t.sum();
myComplexNum.getReal();
But in your code you are trying to do this which you CAN NOT:
a = getNo();
b = sum();
getReal();
Additionally you CAN make the function static like other answer.
static functions and variables does not require an instance. Calling:
// We have 1 Box named b
Box b;
b.setHeight(5);
b.setWidth(3);
b.setDepth(3);
//ClassName::StaticVariable;
int c1 = Box::count; // returns 1
//ClassName::StaticFunction(Parameters);
int c2 = Box::getCount(); // returns 1
When you declare a function (a method) in a class, this method can be called on a instance of this class (a object).
In the given code the function Complex sum (Complex c1, Complex c2); should be called on an object of type Complex.
But as the function doesn't change anything inside the object, it rather creates a new object and returns it, you should better declare a static method.
static Complex sum(Complex, Complex);
in this case you can call the function without an existing Complex object.
The syntax is the following :
r = Complex::sum(a, b);

Derived Classes Error

I finished a small program using derived classes and it compiles correctly, but the output is wrong.
The program uses an ordered pair (x, y) as the center for a circle. It then uses the center and the radius given to determine the area and circumference of the circle.
Outputting ordered pairs with the pointType class works fine, but when I tested the circleType class I expected to get (0, 0) as a default. Instead I got (2293512, 2293700)
Any help given will be appreciated!
Here's the point class code:
#ifndef POINTTYPE_H_INCLUDED
#define POINTTYPE_H_INCLUDED
#include <iostream>
class pointType{
public:
pointType (int=0, int=0);
int getX() const;
int getY() const;
void setX(int);
void setY(int);
void setValues(int, int);
friend pointType operator + (pointType, pointType);
friend pointType operator - (pointType, pointType);
friend std::ostream& operator << (std::ostream&, pointType);
private:
int x;
int y;
};
#endif // POINTTYPE_H_INCLUDED
Here's the point class implementation:
#include "pointType.h"
pointType::pointType (int X, int Y) : x(X), y(Y) {}
int pointType::getX () const {
return x;
}
int pointType::getY () const {
return y;
}
void pointType::setX (int new_x) {
x = new_x;
}
void pointType::setY (int new_y) {
y = new_y;
}
void pointType::setValues (int new_x, int new_y) {
x = new_x;
y = new_y;
}
pointType operator + (pointType lh, pointType rh){
pointType answer;
answer.x = lh.x + rh.x;
answer.y = lh.y + rh.y;
return answer;
}
pointType operator - (pointType lh, pointType rh){
pointType answer;
answer.x = lh.x - rh.x;
answer.y = lh.y - rh.y;
return answer;
}
std::ostream& operator << (std::ostream& out, pointType c){
out << "(" << c.x << ", " << c.y << ")";
return out;
}
Here's the circle class:
#ifndef CIRCLETYPE_H_INCLUDED
#define CIRCLETYPE_H_INCLUDED
#include "pointType.h"
#include <iostream>
class circleType: protected pointType {
public:
circleType (float=0);
circleType (int=0, int=0);
void setRadius (float);
float calculateArea (float);
float calculateCircumference (float);
friend std::ostream& operator << (std::ostream&, circleType);
private:
float radius;
int center_x;
int center_y;
};
#endif // CIRCLETYPE_H_INCLUDED
Here's the circle class implementation:
#include "pointType.h"
#include "circleType.h"
#include <math.h>
const float PI = 3.14;
circleType::circleType(float R): radius(R) {}
circleType::circleType(int center_X, int center_Y):
pointType(center_x, center_y) {}
void circleType::setRadius(float new_radius) {
radius = new_radius;
}
float circleType::calculateArea(float radius) {
float area;
area = PI * pow(radius, 2);
return area;
}
float circleType::calculateCircumference(float radius) {
float circumference;
circumference = PI * (radius * 2);
return circumference;
}
std::ostream& operator << (std::ostream& odata, circleType f) {
odata << "(" << f.center_x << ", " << f.center_y << ")";
return odata;
}
Here's the testing code:
#include "pointType.h"
#include "circleType.h"
#include <iostream>
#include <math.h>
using namespace std;
int main() {
pointType c, d(8, 9);
circleType f(4, 5);
cout << c << endl;
cout << d << endl;
c.setValues(12, 3);
cout << c << endl;
cout << c + d << endl;
cout << c - d << endl;
cout << f << endl;
return 0;
}
As far as I can see, the circleType int members center_x and center_y are never set. Your constructor CircleType::CircleType(int=0,int=0) calls the base constructor, which in turn set pointType.x and pointType.y, both private members of the base class (and hence not available to circleType).
My suggestion (or what I think you intended\expected): make int x and int y protected, not private, and remove center_x and center_y, then print odata << "(" << f.x << ", " << f.y << ")";
Its a typo.
circleType::circleType(int center_X, int center_Y):
pointType(center_x, center_y) {}
Notice the difference between center_X (uppercase) and center_x (lowercase).
You pass your uninitialized members to the parent constructor which can have any value lingering at the stack.
Therefor it is good practive to always preceed your members with m_ e.g: m_centerX. (In this particular case it isnt even neccessary to have them again in the child class, redundancy is bad!)
EDIT:
Sorry for the confusion, but please be more precisly next time, could have saved us all alot of time. I assumed that your problems occurs when adding a point with a circle, after running the code by my own I noticed that it happens when outputting f. The reason is the same as explained above: you dont initialize your members! They simply hold any value which were currently at the memory location the object becomes constructed.
In your circleType class, center_x and center_y aren't being initialised. The parameters are being passed directly to the pointType constructor and setting the private members. You can prove this by changing the operator<< function that takes a circleType argument:
std::ostream& operator << (std::ostream& odata, circleType f) {
odata << "(" << f.center_x << ", " << f.center_y << ")" << std::endl;
odata << "(" << f.getX() << ", " << f.getY() << ")"; //access superclass
return odata;
}
With protected inheritance, you also can't use the + and - overloads defined for the base class either, it won't compile.