Way of overloading operator without changing original values? - c++

I'm wondering if you can overload an operator and use it without changing the object's original values.
Edited code example:
class Rational{
public:
Rational(double n, double d):numerator_(n), denominator_(d){};
Rational(){}; // default constructor
double numerator() const { return numerator_; } // accessor
double denominator() const { return denominator_; } // accessor
private:
double numerator_;
double denominator_;
};
const Rational operator+(const Rational& a, const Rational& b)
{
Rational tmp;
tmp.denominator_ = (a.denominator() * b.denominator());
tmp.numerator_ = (a.numerator() * b.denominator());
tmp.numerator_ += (b.numerator() * a.denominator());
return tmp;
}
I made the accessors const methods, but I'm still getting a privacy error for every tmp.denominator_ / numerator_.

Maybe I'm missing something, but why don't you just take out the code that modifies the arguments?
const Rational Rational::operator+(Rational& num)
{
Rational tmp;
tmp.denominator_ = (denominator_*num.denominator_);
//numerator_*=num.denominator_;
//num.numerator_*=denominator_;
tmp.numerator_ = (numerator_+num.numerator_);
return tmp;
}
This would be caught earlier by being const-correct.
That means your function signature should be this:
Rational Rational::operator+(const Rational& num) const
Then you will get errors because you are modifying const objects. The way your operators are written now is generally considered incorrect.
When you add 2 + 3, neither 2 nor 3 changes: they are const.
Edit
Sorry, I missed the actual math part. Here are a few things:
As a member function (what I have above), do this:
// Note that I use lhs and rhs to refer to the left-hand
// and right-hand sides of an operation. As a member function
// my left-hand side is implicitly `this`.
Rational Rational::operator+(const Rational& rhs) const
{
Rational temp;
temp.denominator_ = (denominator() * rhs.denominator());
temp.numerator_ = (numerator() * rhs.denominator());
temp.numerator_ += (denominator() * rhs.numerator());
return temp;
}
As a global function, do this:
Rational operator+(const Rational& lhs, const Rational& rhs)
{
Rational temp;
temp.denominator_ = (lhs.denominator() * rhs.denominator());
temp.numerator_ = (lhs.numerator() * rhs.denominator());
temp.numerator_ += (lhs.denominator() * rhs.numerator());
return temp;
}
The issue here is you'll get access violations: your member variables are private to the class. You need to let the compiler know that it is okay if this function handles your class's private variables by making the function a friend of the class:
class Rational
{
public:
friend Rational operator+(const Rational& lhs, const Rational& rhs);
}

What you're looking for are the "binary" addition and subtraction operators:
const Rational operator+(const Rational& A, const Rational& B)
{
Rational result;
...
return result;
}
update (in response to new code and comments):
You are getting that error because your accessor functions are not declared as constant functions, so the compiler has to assume that they might modify the original object. Change your accessors as follows, and you should be good to go:
double numerator() const { return numerator_; }
double denominator() const { return denominator_; }
update
To properly handle privacy issues, you should declare the binary operator+ function as a friend of the Rational class. Here is how it would look:
class Rational {
public:
Rational(double n, double d):numerator_(n), denominator_(d) {};
Rational() {}; // default constructor
double numerator() const { return numerator_; } // accessor
double denominator() const { return denominator_; } // accessor
friend Rational operator+(const Rational& A, const Rational& B);
private:
double numerator_;
double denominator_;
};
const Rational operator+(const Rational& a, const Rational& b)
{
Rational result;
result.denominator_ = (a.denominator_ * b.denominator_);
result.numerator_ = (a.numerator_ * b.denominator_);
result.numerator_ += (b.numerator_ * a.denominator_);
return result;
}

no .. you have to rewrite + and - .. it's not that hard. Then change the signatures to
const Rational Rational::operator+(Rational& num) const
const Rational Rational::operator-(Rational& num) const
that way the compiler will let you know if you are modifying your object.

Since your class already provides accessors to the numerator and denominator, and it has a public constructor, there is no need to use any friends. You can overload operator+ as follows:
const Rational operator+(const Rational& rhs, const Rational& lhs)
{
double newNumerator = rhs.numerator() * lhs.denominator() +
rhs.denominator() * lhs.numerator();
return Rational(newNumerator, rhs.denominator() * lhs.denominator());
}
In response to some of the other answers:
Everything about this question is exactly answered by Item 24 of Effective C++ (Third Edition). In this item, Scott Meyers shows that, in cases dealing with numerical types where you want to support implicit conversion in an intuitive manner, it is best to use a non-member non-friend function.
Say your Rational class had the following constructor:
Rational::Rational(double numerator = 0, double denominator = 1);
In this case, if operator+ were a member function, trying to do mixed mode arithmetic would work only half the time:
Rational oneHalf(1, 2);
oneHalf + 2; // works
2 + oneHalf; // error!
In the second example, operator+ for integers is called. The way to fix this is to make operator+ for Rationals a non-member function as shown above.
If you have access to Effective C++, you should also check out Item 23: Prefer non-member non-friend functions to member functions.

I prefer to implement operator+ in terms of operator+=. Then clients get to choose if they want a temp copy or not. Also operator+= is more natural as a member function so it has access to the private parts.
class Rational {
public:
Rational(double n, double d):numerator_(n), denominator_(d) {};
Rational() {}; // default constructor
double numerator() const { return numerator_; } // accessor
double denominator() const { return denominator_; } // accessor
Rational & operator+=(const Rational& b) {
denominator_ *= b.denominator_);
numerator_ *= (b.denominator_);
numerator_ += (b.numerator_ * denominator_);
return *this;
}
private:
double numerator_;
double denominator_;
};
const Rational operator+(const Rational& a, const Rational& b)
{
Rational result(a);
result += b;
return result;
}
However the easiest way to implement operator overloading is to use the boost operators library. Then you implement the minimum set of operators and boost take care of the rest and all the gotchas (including wintermute's example of 2 + oneHalf.

Related

Rational class and Move Semantics not working

I have tried to add more features to already given class(the answer of #Aak) in the problem: How to output fraction instead of decimal number?
for printing fractions in numerator / denominator .
First of all, the given code was not working without any change in the code. Then I made it working after making some changes. However, my implementation gives me a wrong output.
for example:
input: A = 3;
B = 3;
Output: 9/1
9
instead of: 1
here is the complete implementation:
#include <iostream>
/********************** Rational class **********************************/
class Rational
{
private:
int m_numerator, m_denominator;
private:
inline void simplificate()
{
int commondivisor = 1;
for(int i=2;i<= std::min(abs(m_numerator), abs(m_denominator));i++)
if( m_numerator%i == 0 && m_denominator%i == 0 )
commondivisor = i;
m_numerator /= commondivisor;
m_denominator /= commondivisor;
}
public:
Rational() // Defualt
:m_numerator(1), m_denominator(1)
{}
Rational(const int& num, const int& den=1) // Parameterized
:m_numerator(num), m_denominator(den)
{}
Rational(const Rational& other) // Copy
:m_numerator(other.m_numerator), m_denominator(other.m_denominator)
{}
/*Rational(Rational&& other) // Move
:m_numerator(other.m_numerator), m_denominator(other.m_denominator)
{}*/
~Rational(){}
Rational& operator/ (const int& divisor)
{
m_denominator *= divisor;
simplificate();
return *this;
}
Rational& operator/ (const Rational &divisor)
{
m_numerator *= divisor.m_numerator;
m_denominator *= divisor.m_denominator;
simplificate();
return *this;
}
const double getrealformat()const
{
return static_cast<double>(m_numerator)/
static_cast<double>(m_denominator);
}
friend double operator/ (Rational& obj, const int& divisor);
friend void printRational(Rational& obj, const int& A, const int& B);
friend void printRational(Rational& obj, const int&& A, const int&& B);
};
/************************** Friend functions ********************************/
double operator/ (Rational& obj, const int& divisor)
{
obj.m_denominator *= divisor;
obj.simplificate();
return obj.getrealformat();
}
void printRational(Rational& obj, const int& A, const int& B) // lvalue
{
Rational r1(A), r2(B);
obj = r1/r2;
std::cout<<obj.m_numerator<<'/'<<obj.m_denominator<<std::endl;
std::cout<<obj.getrealformat()<<std::endl;
}
void printRational(Rational& obj, const int&& A, const int&& B) // rvalue
{
Rational r1(A), r2(B);
obj = r1/r2;
std::cout<<obj.m_numerator<<'/'<<obj.m_denominator<<std::endl;
std::cout<<obj.getrealformat()<<std::endl;
}
/*****************************************************************************/
int main()
{
Rational obj;
printRational(obj, 3,3);
return 0;
}
Question - 1: the logic looks fine, but I don't know why I am getting the wrong answer. Can anybody find the problem?
Question - 2: I have written "Move" constructor for the class, which you can find in the commented section. However, I could not use it because of following error:
D:\Programming\C++\CPP Programs\Class - Fractions\Class - Fractions.cpp|70|error: use of deleted function 'Rational& Rational::operator=(const Rational&)'|
D:\Programming\C++\CPP Programs\Class - Fractions\Class - Fractions.cpp|77|error: use of deleted function 'Rational& Rational::operator=(const Rational&)'|
(whenever it has been called the moved object/instance is destroyed, to my knowledge.)
can anybody help me to implement the Move constructor for this class?
Look your operator/()
Rational& operator/ (const Rational &divisor)
{
m_numerator *= divisor.m_numerator;
m_denominator *= divisor.m_denominator;
simplificate();
return *this;
}
This code is correct for operator*(), not for operator/().
Maybe
m_numerator *= divisor.m_denominator;
m_denominator *= divisor.m_numerator;
But is worse that you're operator/() modify the object.
Your code (corrected switching numerator and denominator) should be correct for operator/=(), not for operator/() that should return a new object.
I suggest something as follows
Rational& operator/= (const Rational &divisor)
{
m_numerator *= divisor.m_denominator;
m_denominator *= divisor.m_numerator;
simplificate();
return *this;
}
friend Rational operator/ (Rational A, Rational const & B);
and, outside the class,
Rational operator/ (Rational A, Rational const & B)
{ return A/=B; }
Regarding question 2 ("I have written "Move" constructor for the class, [...]However, I could not use it because of following error"), you can see in this page that
A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
T has a user-declared move constructor;
T has a user-declared move assignment operator.
So, when you define the move contructor, you delete the implicit copy operator.
You can solve the problem adding
Rational & operator= (Rational const &) = default;
reactivating the implicit copy constructor

class functions with constant object parameter?

My assignment requires that I write a program that performs the rational number operations addition, subtraction, multiplication and division on two fractions. They must be class objects with variables numerator and denominator. I am given a header that I may not change:
class Rational
{
private:
int numer;
int denom;
public:
Rational();
Rational(int);
Rational(int, int);
const Rational add(const Rational &) const;
const Rational subtract(const Rational &) const;
const Rational multiply(const Rational &) const;
const Rational divide(const Rational &) const;
void display() const;
};
For example, if given fractions a, b, and c, I must multiply a with b and store it in c:
c = a.multiply(b)
The function definition I've come up with is something like
const Rational Rational::multiply(const Rational &) const
{
return a.numer*numer, a.denom*denom;
}
The object a is undefined in the function, but I have no other ideas as to how I can pass in a class object as a variable and multiply it to another class.
Give the parameter a name,
Correctly construct the result object and return it.
const Rational Rational::multiply(const Rational & a) const
{
return {a.numer*numer, a.denom*denom};
}
You need to use the two-parameter class constructor in your return statement.
return Rational(a.numer*numer, a.denom*denom);
const Rational Rational::multiply(const Rational & rhs) const
{
return Rational{numer * rhs.numer, denom * rhs.denom};
}

Error while overloading operator +,-,*,/ in c++ [duplicate]

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();

expression must be a modifiable lvalue in my class

I know what it means but in my situation I don't understand why my IDE yelling me about this.
Rational operator*(const Rational& that1, const Rational& that2)
{
Rational temp(that1);
temp.getNom() *= that2.getNom();
temp.getDenom() *= that2.getDenom();
return temp;
}
int Rational::getNom() const
{
return m_iNom / gcd(m_iNom, m_iDenom);
}
int Rational::getDenom() const
{
return m_iDenom / gcd(m_iNom, m_iDenom);
}
float Rational::gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
m_iNom & m_iDenom are private data members inside Rational class.
I'm getting 'expression must be a modifiable lvalue' at :
temp.getNom() *= that2.getNom();
temp.getDenom() *= that2.getDenom();
You cannot affect a value to a function or method return.
temp.getNom() *= that2.getNom(); is like temp.getNom() = temp.getNom() * that2.getNom();
It's like to write 2 = 2 * 3 and set 2 = 5 … no sense!
As the compiler says, you can't assign to the return value.
Even if you could assign to the return value, the member variables would be unaffected —
the accessors return the values of the member variables, not the actual variables.
The idiomatic way of doing this is to first implement operator *= as a member:
Rational& operator *= (const Rational& that)
{
m_iNom *= that.m_iNom;
m_iDenom *= that.m_iDenom;
return *this;
}
and then use that to implement *:
Rational operator*(const Rational& that1, const Rational& that2)
{
Rational result(that1);
result *= that2;
return result;
}

C++ error with operator overloading

I am trying to make program that uses operator overloading to do basic math operations on rational numbers. I keep getting an errors in the functions where it says i must have an arithmetic of enum type. Also I get an error istream where it says that the numerator and denominator are undefined.
Here is the header file:
#ifndef rational_H
#define rational_H
#include <iostream>
using namespace std;
class Rational
{
friend ostream & operator<<(ostream & , const Rational &);
friend istream & operator<<(istream & , const Rational &);
public:
// default constructor
Rational(int = 0, int = 1);
// overload operators for "normal" operation
Rational operator+(const Rational&);
Rational operator-(const Rational&);
Rational operator*(const Rational&);
Rational operator/(const Rational&);
operator double();
// overload relational operators for "normal" operation
bool operator>(const Rational&) const;
bool operator<(const Rational&) const;
bool operator>=(const Rational&) const;
bool operator<=(const Rational&) const;
bool operator==(const Rational&) const;
bool operator!=(const Rational&) const;
protected:
int *numerator;
int *denominator;
void reduction(void);
};
#endif
// this part of code is from my rational cpp file//
// default constructor//
Rational::Rational( int n, int d )
{
*numerator =1 ;
// sets numerator
if(d == 0)
d = 1; // If denominator is zero then set to one.
*denominator = 0;
// sets denominator
reduction(); // store the fraction in reduced form
}
// all the other operators have the same error as well//
Rational Rational::operator-(const Rational&a)
{
Rational sub;
sub.numerator = *this->numerator * a.denominator -//the error is with the 'a'needs to be an arithmetic type or enum type//
*this->denominator * a.numerator;
sub.denominator = *denominator * a.denominator;
sub.reduction();
return sub;
}
//also the istream part has an error where the denominator and numerator is underfined as well//
istream& operator >> ( istream& inputStream, Rational& rnum )
{
inputStream>>rnum.*numerator;//numerator and denmoinator undefined for some reason//
inputStream.ignore(1);
inputStream>>rnum.*denominator;
return inputStream;
}
There are multiples small errors in your code.
First of all you should not be using pointers for these members, it does not bring any advantages.
But as you chose this way, you have to dereference them each time you want to read or update them, which hasn't be done in your operator- implementation, and incorrectly in your operator>> implementation (the asterisk needs to be put before the whole expression).
Next error in the code you provided, you marked as friend operator<<(istream & , const Rational &) in your class definition, but it should have been operator>>. And this declaration needs to match the definition that appears next (i.e., remove the const of the second argument, which obviously has to be mutated).
And, last but not least, the undefined behavior caused by all the dereferencing of you uninitialized pointers…
This is probably a copy and past error. The line
friend istream & operator<<(istream & , const Rational &);
should be
friend istream & operator>>(istream & , Rational &);
Your implementation later on in the file has:
istream& operator >> ( istream& inputStream, Rational& rnum )
{
...
}
It matches the second declaration, not the first one.