I was trying to make a Complex class which would represent the Complex numbers in c++ but I have encountered an error. The copy constructor seems to be the problem but I am not sure as to what is wrong or why it is wrong. The / operator works well as I return a reference to an object of Complex class. but the * operator does not works when I return an object of Complex class. Please explain this behaviour,
edit: I have used the new operator and a custom copy constructor as it was a requirement of my school to dynamically allocate memory.
here is my code.
#include <iostream>
using namespace std;
class Complex
{
public:
double r, i;
Complex() : r(0), i(0) {}
Complex(int r, int i)
{
this->r = double(r);
this->i = double(i);
}
Complex(double r, int i)
{
this->r = r;
this->i = double(i);
}
Complex(int r, double i)
{
this->r = double(r);
this->i = i;
}
Complex(double r, double i)
{
this->r = r;
this->i = i;
}
Complex(Complex &c)
{
cout<<"cpy constructor called"<<endl;
r = c.r;
i = c.i;
}
void operator()(float r, float i)
{
this->r = r;
this->i = i;
}
void operator()(int r, int i)
{
this->r = r;
this->i = i;
}
Complex operator+(Complex &c)
{
Complex *c1 = new Complex(r + c.r, i + c.i);
return *c1;
}
Complex operator-(Complex &c)
{
Complex *c1 = new Complex(r - c.r, i - c.i);
return *c1;
}
Complex operator*(Complex &c)
{
Complex *c1 = new Complex(
r * c.r + (-1) * (i * c.i),
r * c.i + i * c.r);
return *c1;
}
Complex& operator/(Complex &c)
{
float dem;
Complex num;
num = (*this) * * (new Complex(c.r,-c.i));
dem = c.r*c.r + (c.i*c.i);
Complex *c1 = new Complex(num.r/dem,num.i/dem);
return *c1;
}
operator string()
{
string temp, s;
temp = to_string(r);
while (true)
{
if (temp[temp.length() - 1] == '0')
{
temp.pop_back();
}
else
break;
}
if (temp[temp.length() - 1] == '.')
temp.pop_back();
s += temp;
if (i >= 0)
{
s += '+';
}
temp = to_string(i);
while (true)
{
if (temp[temp.length() - 1] == '0')
{
temp.pop_back();
}
else
break;
}
if (temp[temp.length() - 1] == '.')
temp.pop_back();
s += temp;
s += 'i';
return s;
}
friend ostream &operator<<(ostream &out, Complex c);
};
ostream& operator<<(ostream &out, Complex c)
{
out << string(c);
return out;
}
int main()
{
Complex c(5, 5);
Complex d(5,5);
cout << c/d <<endl;
cout<< c*d <<endl;
}
and this is the error I encounter after this
test.cpp: In function 'int main()':
test.cpp:123:13: error: invalid initialization of non-const reference of type 'Complex&' from an rvalue of type 'Complex'
cout<< c*d <<endl;
~^~
test.cpp:31:5: note: initializing argument 1 of 'Complex::Complex(Complex&)'
Complex(Complex &c)
^~~~~~~
test.cpp:111:10: note: initializing argument 2 of 'std::ostream& operator<<(std::ostream&, Complex)'
ostream& operator<<(ostream &out, Complex c)
This is the image to the error
Repeat the pattern of the code below for your other operators. Note the operator takes the parameter by const ref and returns the result by value:
Complex operator+(Complex const &c)
{
return Complex(r + c.r, i + c.i);
}
The copy constructor should also be changed to take it's parameter by const ref ie
Complex(Complex const &c)
{
r = c.r;
i = c.i;
}
The minimal fix isComplex(Complex &c) -> Complex(const Complex &c)
But then there will remain leaks due to the inappropriate usage of new there, after some cleanup:
#include <iostream>
using namespace std;
class Complex
{
public:
double r, i;
Complex(double r, double i) : r(r), i(i) {}
Complex operator+(Complex c)
{
return Complex(r + c.r, i + c.i);
}
Complex operator-(Complex c)
{
return Complex(r - c.r, i - c.i);
}
Complex operator*(Complex c)
{
return Complex(
r * c.r + (-1) * (i * c.i),
r * c.i + i * c.r);
}
Complex operator/(Complex c)
{
auto num = Complex (*this) * Complex(c.r,-c.i);
auto dem = c.r*c.r + (c.i*c.i);
return Complex(num.r/dem,num.i/dem);
}
operator string()
{
string temp, s;
temp = to_string(r);
while (!temp.empty() && temp.back() == '0')
temp.pop_back();
if (!temp.empty() && temp.back() == '.')
temp.pop_back();
s += temp;
if (i >= 0)
{
s += '+';
}
temp = to_string(i);
while (!temp.empty() && temp.back() == '0')
temp.pop_back();
if (!temp.empty() && temp.back() == '.')
temp.pop_back();
s += temp;
s += 'i';
return s;
}
friend ostream &operator<<(ostream &out, Complex c);
};
ostream& operator<<(ostream &out, Complex c)
{
out << string(c);
return out;
}
int main()
{
Complex c(5, 5);
Complex d(5,5);
cout << c/d <<endl;
cout<< c*d <<endl;
}
The big problem is lack of const on your references and members. The second problem is not using =default. The third problem is too many overloads. Forth, your new use is wrong. operstor() are all wrong. The last problem is your operator strategy. And don't use namespace std;.
struct Complex
Complex is both default public and basically an aggregate. I'd use struct
{
double r=0
double i=0;
you can do default initialization in C++ now.
Complex()=default;
now this ctor is auto-written, because we initialized the members at declaration. DRY is "don't repeat yourself"; when easy, don't repeat member names.
Complex(double r_in, double i_in):r(r_in),i(i_in){}
ctors should construct, not assign, members.
Drop the other 2 arg ctors. Callers can convert.
Complex(Complex const&c)=default;
const here, and let the compiler write a member-wise copy with =default; DRY.
Complex(Complex &&c)=default;
Complex& operator=(Complex const&c)=default;
Complex& operator=(Complex &&c)=default;
also assignment and moves
Now other operators...
Complex& operator+=(Complex const& o)&{
implement a+=b before +.
r+=o.r;
i+=o.i;
return *this;
}
here we repeat member names; it isn't easy to avoid.
Do the same for -= and *=
Next,
friend Complex operator+(Complex lhs, Complex const& rhs){
lhs+=rhs;
return lhs;
}
this makes a non-member +. It makes a copy of its left hand argument by taking it by value, and a const reference to its right hand argument.
We then increment the left hand copy by the right, and return it.
This pattern chans wonderfully in 99% of situations;
Complex x=a+b+c
becomes
Complex x=a;
x+=b;
x+=c;
after accounting for moves and elision.
And you get a+=b; and a+b by writing only one member-wise operation.
Just don't use your operator(), they are nonsense.
Related
I am new to C++ (coming from Python and C) so operator overloading is completely new to me.
I have been trying to overload the << operator to be able to represent a string version of a vector class I'm writing, but I keep on getting a (lengthy) build FAILED error, starting with: "Undefined symbols for architecture x86_64:".
These are the parts of my code involved in the issue:
//
// Created by mario on 10/03/2022.
//
#include <cstdio>
#include <string>
#include <cmath>
class vector3D {
public:
double x;
double y;
double z;
explicit vector3D(double xPos = 0, double yPos = 0, double zPos = 0) : x(xPos), y(yPos), z(zPos) {}
std::string to_str() const {
std::string x_str = std::to_string(x);
std::string y_str = std::to_string(y);
std::string z_str = std::to_string(z);
return x_str + "i + " + y_str + "j + " + z_str + "k";
}
double mag() {
return sqrt(x*x + y*y + z*z);
}
};
vector3D operator*(vector3D A, vector3D B) {
return vector3D(A.x*B.x, A.y*B.y, A.z*B.z);
}
int operator==(vector3D a, vector3D b) {
return (a.x == b.x && a.y == b.y && a.z == b.z) ? 1 : 0;
}
std::ostream &operator<<(std::ostream &out, const vector3D &vec) {
out << vec.to_str();
return out;
}
int main() {
vector3D vec1(4, 3, 1);
vector3D vec2(3, 3, 2);
printf("%lf %s\n", vec1.mag(), (vec1*vec2).to_str().c_str());
return 0;
}
I managed to successfully overload the * and == operators, but not <<.
Any help would be much appreciated, thank you!
Edit: after a suggestion in the comments that I should include a reproducible example, I have included the entire code, since it's just about 15 lines longer than what I posted earlier.
Note: it seems though I only get the compilation error on mac - very strange.
I created a code by using operator overloading concept in c++ for addition of two rational numbers by overloading the +(plus) and the <<(Insertion) operator and I am not able to get a function being accessed from the scope of operator overloading of + operator. How to access the LCM() function from the scope of operator+ overloaded?
I tried using the friend function to access my LCM() function from within the scope of operator+ overloaded function but it didn't work!
#include <iostream>
using namespace std;
class Rational {
private:
int num, den;
public:
int getnum()
{
return this->num;
}
int getden()
{
return this->den;
}
Rational(int num = 0, int den = 0)
{
this->num = num;
this->den = den;
}
int LCM(int a, int b);
friend ostream& operator<<(ostream& out, Rational& r);
friend Rational operator+(Rational x, Rational y);
};
int Rational::LCM(int a, int b)
{
int i = a > b ? a : b;
for (i; i <= a * b; i++) {
if (i % a == 0 && i % b == 0) {
break;
}
}
return i;
}
ostream& operator<<(ostream& out, Rational& r)
{
out << r.getnum() << "/" << r.getden();
return out;
}
Rational operator+(Rational x, Rational y)
{
Rational temp;
int temp1;
int div;
temp1 = LCM(x.den, y.den);
temp.num = (int(temp1 / x.den) * x.num) + (int(temp1 / y.den) * y.num);
temp.den = temp1;
return temp;
}
int main()
{
Rational r1(3, 2);
Rational r2(9, 4);
Rational r3;
r3 = r1 + r2;
cout << r3;
return 0;
}
And I get the error:
error: ‘LCM’ was not declared in this scope
I would say that int Rational::LCM(int a,int b) does not really have anything to do with the Rational class and should probably be a utility function (non-member function), then you would be able to use it anywhere
I am a beginner in C++. I am learning on how to overload operators. I have created a class Complex that represents complex numbers and methods for complex arithmetic and a class ComplexArray that represents fixed-length arrays of elements in complex vector space C.
I get compiler errors, that it is unable to find the correct form of operator[]. However, I searched the internet and I am unable to rectify the error. Any hints/tips in the right direction would be of tremendous help.
Severity Code Description Project File Line Suppression State
Error C2676 binary '[': 'const ComplexArray' does not define this operator or a conversion to a type acceptable to the predefined operator ComplexArrays c:\users\quasa\source\repos\complexarrays\complexarrays\testcomplexarray.cpp 7
Here is my code:
TestComplexArray.cpp
#include <iostream>
#include "ComplexArray.h"
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < size; i++)
{
sum = sum + cArray[i];
}
return sum;
}
Complex ComplexProduct(const ComplexArray& cArray, int size)
{
Complex product = cArray[0];
for (int j = 1; j < size; j++)
{
product = product * cArray[j];
}
return product;
}
int main()
{
char ch;
const int size = 5;
ComplexArray cArray(size);
for (int i = 0; i < size; i++)
{
cArray[i] = Complex((double)(i + 1), 0);
std::cout << cArray[i];
}
Complex sum = ComplexSum(cArray, size);
Complex product = ComplexProduct(cArray, size);
std::cout << "Sum = " << sum << std::endl;
std::cout << "Product = " << product << std::endl;
std::cin >> ch;
return 0;
}
ComplexArray.h
class ComplexArray
{
private:
Complex* complexArr;
int size;
ComplexArray();
public:
//Constructors and destructors
ComplexArray(int size);
ComplexArray(const ComplexArray& source);
virtual ~ComplexArray();
//Range for the complexArr
int MaxIndex() const;
//Overload the indexing operator
const Complex& operator [](int index) const;
Complex& operator [](int index);
};
ComplexArray.cpp
#include "Complex.h"
#include "ComplexArray.h"
ComplexArray::ComplexArray(int s)
{
size = s;
complexArr = new Complex[size];
}
ComplexArray::ComplexArray(const ComplexArray& source)
{
//Deep copy source
size = source.size;
complexArr = new Complex[size];
for (int i = 0; i < size; i++)
{
complexArr[i] = source.complexArr[i];
}
}
ComplexArray::~ComplexArray()
{
delete[] complexArr;
}
int ComplexArray::MaxIndex() const
{
return (size - 1);
}
/*
c1.operator[](int index) should return a reference to the Complex
object, because there are two possible cases.
Case 1:
Complex c = complexArray[3];
Case 2:
complexArray[3] = c;
In the second case, complexArray[3] is an lvalue, so it must return
a Complex object by reference, so that it can be assigned to.
*/
const Complex& ComplexArray::operator[] (int index) const
{
return complexArr[index];
}
Complex& ComplexArray::operator[](int index)
{
return complexArr[index];
}
Complex.h
#include <iostream>
class Complex
{
private:
double x;
double y;
void init(double xs, double ys); //Private helper function
public:
//Constructors and destructors
Complex();
Complex(const Complex& z);
Complex(double xs, double ys);
virtual ~Complex();
//Selectors
double X() const;
double Y() const;
//Modifiers
void X(double xs);
void Y(double ys);
//Overload binary +, = and * operators
Complex operator + (const Complex& z);
Complex& operator = (const Complex& z);
Complex operator * (const Complex& z) const;
//Overload unary - operator
Complex operator -() const;
friend Complex operator * (const double alpha, const Complex& z);
friend Complex operator * (const Complex& z, const double beta);
//Overload << operator
friend std::ostream& operator << (std::ostream& os, const Complex& z);
//A complex function f(z)=z^2
Complex square();
};
As you have all pointed out - I was missing the forward definition of a #include.
Complex.cpp has the header
#include "Complex.h"
ComplexArray.h has the header
#include "Complex.h"
ComplexArray.cpp has the header
#include "ComplexArray.h"
TestComplexNumbers.cpp has the header
#include <iostream>
#include "ComplexArray.h"
My compile-time errors have been resolved.
I don't think the error comes from operator[], as you can see in the function:
Complex ComplexSum(const ComplexArray& cArray, int size)
{
Complex sum = cArray[0];
for (int i = 1; i < cArray.MaxIndex(); i++)
{
sum = sum + cArray[i];
}
}
You don't return a result. That's fatal.
ComplexArray depends on Complex but order of includes doesn't look right
#include "ComplexArray.h"
#include "Complex.h"
You have to forward-declare Complex before ComplexArray
class Complex;
Code fails at \testcomplexarray.cpp line 7 which is
Complex sum = cArray[0];
It looks like you have problem with ctors of Complex. Be sure that you have NOT defined such:
Complex(Complex& v); // that's bad. it prevents to use copy constructor
If you need copy ctor for some inconceivable reason, it always should look so:
Complex(const Complex& v);
I am a beginner at C++ and I am trying to make a program that uses 2 points, adds them together to a line. Then adds a line together with a point, and gets a polygon.
I am trying, unsuccessfully, to overload the operator << so that I can print out my line:
#include <iostream>
using namespace std;
class Line {
private:
OnePoint onevalue;
OnePoint twovalue;
public:
Line(OnePoint a, OnePoint b) {
onevalue = a;
twovalue = b;
}
ostream& operator<<(ostream& print, Line& linje){ // Error right here.
print << linje.onevalue << ',' << linje.twovalue; // Too many
return print; // parameters for this type of function
}
};
class OnePoint {
private:
double xvalue;
double yvalue;
public:
OnePoint(double x = 0.0, double y = 0.0) {
xvalue = x;
yvalue = y;
}
friend ostream& operator<<(ostream& printh, OnePoint& cPoint) {
printh << "(" << cPoint.xvalue << ',' << cPoint.yvalue << ")";
return printh;
}
void Plus(OnePoint a) {
xvalue = xvalue + a.xvalue;
yvalue = yvalue + a.yvalue;
}
void Minus(OnePoint b) {
xvalue = xvalue + b.xvalue;
yvalue = yvalue + b.yvalue;
}
OnePoint Plustwo(OnePoint a) {
return (xvalue + a.xvalue, yvalue - a.yvalue);
}
void Change(double a, double b) {
xvalue += a;
yvalue += b;
}
void Print(OnePoint b) {
cout << xvalue << "," << yvalue << endl;
}
OnePoint operator+(OnePoint a) {
OnePoint temp;
temp.xvalue = xvalue + a.xvalue;
temp.yvalue = yvalue + a.yvalue;
return temp;
}
};
//--------------------------------------------------------------------
int main(){
OnePoint a(3.0, 3.0);
OnePoint b(1.0, 1.0);
OnePoint d(1.0, 4.0);
OnePoint c;
c = a + b + d;
c.Print(c);
}
Edit:
I can now cout my OnePoint, but I cannot cout Line.
As a member function, the operator gets an extra hidden parameter for the this pointer.
You can make it a free function by declaring it a friend of the class:
class Line {
// other members
public:
friend ostream& operator<<(ostream& print, Line& linje){
print << linje.onevalue << ',' << linje.twovalue;
return print;
}
};
I am struggling with adding operations of classes Natural, Rational, Complex that represent appropriate math objects. I need that to calculate polynomial in x.
All classes inherit abstract class Number. Having all coefficients in an array of Numbers I want to calculate the polynomial. To do so I need operation of multiplying by double (x is double). x gets transformed into Rational and multiplied. This works fine. My problem is how to add classes of abstract type Number?
I can't make it work. All I get is never ending recursion in Number::add(Number) (it invokes itself instead of invoking others methods for types Natural, Rational, Complex).
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Natural;class Rational;class Complex;
class Number {
public:
virtual string toString() const = 0;
virtual Number *operator*(const Rational) const = 0;
virtual Number *add(const Natural*) const = 0;
virtual Number *add(const Rational*) const = 0;
virtual Number *add(const Complex*) const = 0;
virtual Number *add(const Number *n) const {
n->add(this);
}
};
class Natural : public Number {
friend class Complex;
int n;
public:
Natural(const Natural &s) {
n = s.n;
}
Natural(int number) : n(number) {}
string toString() const {
stringstream ss;
ss << n;
return ss.str();
}
operator Rational() const;
operator Complex() const;
operator int() const {
return n;
}
Number *operator*(const Rational r) const;
Number *add(const Natural* number) const {
return new Natural(n + number->n);
}
Number *add(const Rational*) const;
Number *add(const Complex*) const;
};
class Rational : public Number {
friend class Natural;
int numerator, denominator;
void divideByGCD() {
int a = numerator, b = denominator;
//cout << a << ' ' << b << ' ';
if(a < b) {
int temp = a;
a = b;
b = temp;
}
while (b > 0) {
int r = a % b;
a = b; b = r;
//cout << r << endl;
}
numerator /= a;
denominator /= a;
//cout << a << endl;
}
public:
Rational() {}
Rational(const Rational &s) {
numerator = s.numerator;
denominator = s.denominator;
}
Rational(int n, int d) {
if(d == 0) throw new runtime_error("denominator equals 0");
if(d < 0) {
numerator = -n;
denominator = -d;
} else {
numerator = n;
denominator = d;
}
divideByGCD();
}
Rational(double d) {
int i = 0, mul = 1;
int r = d-floor(d);;
while(r!=0) {
i++; mul *= 10;
r = 10*r-floor(10*r);
}
numerator = (int)mul*d;
denominator = mul;
divideByGCD();
}
string toString() const {
stringstream ss;
ss << numerator;
if(denominator > 1) ss << '/' << denominator;
return ss.str();
}
operator const Complex() const;
operator const double() const {
return (double)numerator/denominator;
}
Number *operator*(const Rational r) const {
return new Rational(numerator*r.numerator, denominator*r.denominator);
}
Number *add(const Rational* r) const {
return new Rational(numerator*r->denominator+r->numerator*denominator, denominator*r->denominator);
}
Number *add(const Natural*) const;
Number *add(const Complex*) const;
};
class Complex : public Number {
friend class Rational;
double real, imaginary;
static const double radius = 10;
public:
Complex() {}
Complex(const Complex &s) {
real = s.real;
imaginary = s.imaginary;
}
Complex(const double r, const double im) : real(r), imaginary(im) {}
string toString() const {
stringstream ss;
ss << real;
if(imaginary != 0) ss << '+' << imaginary << 'i';
return ss.str();
}
Number *operator*(const Rational r) const;
Number *add(const Complex* c) const {
return new Complex(real + c->real, imaginary + c->imaginary);
}
Number *add(const Natural*) const;
Number *add(const Rational*) const;
};
Natural::operator Rational() const {
return Rational(n,1);
}
Natural::operator Complex() const {
return Complex(n, 0);
}
Rational::operator const Complex() const {
return Complex((double)numerator/denominator, 0);
}
Number *Natural::operator*(const Rational r) const {
return new Rational(n*r.numerator, r.denominator);
}
Number *Complex::operator*(const Rational r) const {
return new Complex(real*(double)r, imaginary*(double)r);
}
Number *Natural::add(const Rational *r) const {
if(r->denominator == 1) return new Natural(n+r->numerator);
else return new Rational(n*r->denominator,r->denominator);
}
Number *Natural::add(const Complex *c) const {
return c->add(this);
}
Number *Rational::add(const Natural *n) const {
return n->add(this);
}
Number *Rational::add(const Complex *c) const {
return new Complex(c->real+(double)*this, c->imaginary);
}
Number *Complex::add(const Natural *number) const {
return new Complex(real+number->n, imaginary);
}
Number *Complex::add(const Rational *r) const {
return r->add(this);
}
Number *poly(double x, Number *a[], unsigned int size) {
if(size == 1) return a[0];
else return a[0]->add((*poly(x, a+1, size-1))*Rational(x));
}
int main() {
cout << (Natural(5)*(Rational)2.0)->toString() << endl;
Number *coefs[] = {new Natural(5), new Natural(6)};
cout << poly(2, coefs, 2) << endl;
}
How should I fix Number::add(Number) so that while invoking add on object of type Number program itself figure out which of virtual method add to choose?
This is known as multi-dispatch. Here are some links to look at
Multiple_dispatch
best multimethods implementation
I think the problem is:
virtual Number *add(const Number *n) const {
n->add(this);
}
If you multiply a Rational by a Natural that is stored in a Number *, it can't polymorphicly upcast the Number * to a Natural *. I agree w/g-makulik in that references/values make a lot more sense here, as you are leaking memory all over the place. Remove support for Number + Number. Also, if I add a Natural and a Rational together, I get a Number * back, but what kind of number is it? I think the architecture needs a bit more thought; I might get rid of the base class pure virtual methods entirely (except maybe toString). For example:
class Number
{
public:
virtual string toString() = 0;
};
class Rational : public Number
{
string toString() {...}
// forget 'add', use operators
Rational operator+(const Rational & _rhs) const {Rational ret; ...; return ret;}
Rational & operator+=(const Rational & _rhs) const {...; return *this;}
...
}
Edit
For a quick fix, I think you just need to get rid of virtual Number *operator*(const Rational) const = 0;, and replace it with a version for each sub-class (e.x., Rational * operator*(const Natural) const)
Or, add an enumerated member variable to Number to keep track of the type:
enum Type { NATURAL, RATIONAL, ...}
Type mType;
or use RTTI, such that you can selectively choose the right add method in Number::add:
Number * add(Number * _rhs)
{
if(_rhs->mType == RATIONAL)
return this->add((Rational *)_rhs);
...
}
it looks kinda sloppy, but it will work
it looks like Visitor pattern is what I've been looking for. I wanted to have functions accept and visit in the same class. I believe my mistake was to give them the same name.