class Fraction
{
friend Fraction operator+(const Fraction& f1, const Fraction& f2);
private:
int numerator;
int denominator;
};
--------------------------------------------------------------------
Fraction operator+(const Fraction& f1, const Fraction& f2)
{
Fraction r; // declare a Fraction to hold the result
// load result Fraction with sum of adjusted numerators
r.numerator = (f1.numerator*f2.denominator)
+ (f2.numerator*f1.denominator);
// load result with the common denominator
r.denominator = f1.denominator * f2.denominator;
return r; // return the result Fraction
}
Is there a way to make Operator+ add fraction (from Fraction class) with integer?
Example:
Fraction frac(7/15), x = frac + 13;
Yes it is possible, although I wouldn't do it that way.
Presumably (in your real code) you have a constructor for Fraction that takes two arguments: a numerator and a denominator. Make the denominator a default argument set to 1.
Then you will not need any more overloads to +, or any extra overloads that you intend to support over time (e.g. -, *, &c.).
Related
I am trying to implement a Fraction class, which calculates the product of two fractions. It compiles fine but doesn't accept input and abruptly ends.
Here is my code:
#include<iostream>
#include<cmath>
using namespace std;
class Fraction{
int m_numerator{0},m_denominator{1};
public:
Fraction(int numerator=0,int denominator=1):m_numerator{numerator},m_denominator{denominator}{
}
friend Fraction operator*(const Fraction &f1,const Fraction &f2);
friend Fraction operator*(const Fraction &f,int n);
friend Fraction operator*(int n,const Fraction &f);
friend ostream &operator<<(ostream &out,const Fraction &f){
out<<f.m_numerator<<'/'<<f.m_denominator;
return out;
}
friend istream &operator>>(istream &in,const Fraction &f);
};
istream &operator>>(istream &in,const Fraction &f){
in>>f.m_numerator;
in>>f.m_denominator;
return in;
}
Fraction operator*(const Fraction &f1,const Fraction &f2){
return Fraction{f1.m_numerator*f2.m_numerator,f1.m_denominator*f2.m_denominator};
}
Fraction operator*(const Fraction &f,int n){
return Fraction(n*f.m_numerator,f.m_denominator);
}
Fraction operator*(int n,const Fraction &f){
return Fraction(n*f.m_numerator,f.m_denominator);
}
int main(){
Fraction f1;
cin>>f1;
Fraction f2;
cin>>f2;
std::cout << f1 << " * " << f2 << " is " << f1 * f2 << '\n';
return 0;
}
Can anyone please tell me where I am wrong?
The problem is the const qualifier on the second argument of your operator>>. First, this seems a bit weird, as you want to modify the values when they are given as input. Second, as there is no default overload for the >> operator that takes a const int operand, the best (only?) match for the internal >> operations is the function itself – and this causes infinite recursion.
To fix the issue, just remove that const qualifier:
istream& operator>>(istream& in, Fraction& f)
{
in >> f.m_numerator;
in >> f.m_denominator;
return in;
}
(And similarly, in the declaration.)
Note: To address the point made in the comments, about properly reading a fraction specified with a slash (i.e. input like 3/4), you can simply add the following line between the two lines that read the numerator and denominator:
char slash; in >> slash; // Skip the slash.
The reason why you are running into an error is because you have an infinite recursion. Let's observe this snippet:
istream &operator>>(istream &in,const Fraction &f){
in>>f.m_numerator;
in>>f.m_denominator;
return in;
}
Here you have istream >> int, and since Fraction has a non-explicit constructor which can be initialized with f.m_numerator, you are effectivelly calling the same operator again. What you probably want is to call the operator cin>>int. So simplest way would be to just define the constructor as explicit. But this is only solution to the problem "why does it compile if it's wrong (or at least not what I wanted)?"
The other issue you have is the fact that you are trying to use istream>>const int&, since the fraction is passed by const reference, you aren't able to change the const (inherited) member (i.e. call the operator istream>>int&.
Class fraction
{
public:
fraction operator+ (const fraction& fr) const;
private:
int num; //numerator
int den; //denominator
};
I wanted to overlaod the operator+ so that it perfoms the multiplication of an integer constant (calling object) and a fraction.
fraction fraction::operator+ (const fraction& fr) const
{
fraction result;
result.num = fr.num + fr.den * (*this);
//error message says invalid operands to binary exprssion ('int' and 'constant fraction')
result.den = fr.den;
simplified_fr(result); // a helper function to simplify the resulted fraction
return result;
}
It seems that the problem is about the type of calling object. I intended to make it a constant integer but the computer thought it was a 'const fraction'. Can someone please advise me why this happened and how can I fix it? Thank you in advance!!!
I assume you would like to do achieve something like this:
fraction fract;
fraction fract2 = 2 + fract;
The answer is that you cannot overload member method operator+ for non-class objects. BUT you can define/overload global operator+ function:
fraction operator+(int num, const fraction& rFrac)
{
//your implementation
}
You will probably need access to private members of fraction class. That can be acomplished by making operator+ a friend:
class fraction
{
//...
friend fraction operator+(int num, const fraction& rFrac);
//...
}
I am getting no match for 'operator +' error in main section.
I overloaded all of the operators as friend except =
I tried to debug but could not figured it out
I don't know, what I am skipping.
Please advise.
#include <iostream>
using namespace std;
class fraction
{
long num;
long den;
public:
fraction( ){num = 0L ; den = 1L ;}
fraction(long l_num,long l_den){num = l_num ; den = l_den ;}
fraction(const fraction& f){num=f.num; den=f.den;}
~fraction ( ){}
long getNum (void) const{return num ;}
long getDen (void) const{return den ;}
void print(void)
{
if(den==0)den=1L;
cout<<num<<"/"<<den <<endl;
}
fraction inc ( )
{
long numX = (num) + (den);
long denY = (den);
return fraction(numX, denY );
}
friend fraction operator +(fraction &f1 , fraction &f2);
friend fraction operator +(int i, fraction &f2);
friend fraction &operator++(fraction & f1);
fraction operator =( const fraction &f);
friend fraction operator -(fraction &f1 , fraction &f2);
friend fraction operator *(fraction &f1 , fraction &f2);
friend fraction operator /(fraction &f1 , fraction &f2);
};
inline fraction operator +(fraction &f1, fraction &f2)
{
fraction temp;
temp.num=(f1.num*f2.den)+(f1.den*f2.num);
temp.den=f1.den*f2.den;
return temp;
}
inline fraction operator +(int i, fraction &f2)
{
fraction temp;
temp.num=i*f2.den+f2.num;
temp.den=f2.den;
return temp;
}
inline fraction &operator++(fraction& f1)
{
f1.num=f1.num+f1.den;
return f1;
}
inline fraction fraction::operator=(const fraction &f)
{
num=f.num;
den=f.den;
return*this;
}
inline fraction operator -(fraction &f1, fraction &f2)
{
fraction temp;
temp.num=(f1.num*f2.den)-(f1.den*f2.num);
temp.den=f1.den*f2.den;
return temp;
}
inline fraction operator *(fraction &f1, fraction &f2)
{
fraction temp;
temp.num=f1.num*f2.num;
temp.den=f1.den*f2.den;
return temp;
}
inline fraction operator /(fraction &f1 , fraction &f2)
{
fraction temp;
temp.num=f1.num*f2.den;
temp.den=f1.den*f2.num;
return temp;
}
int main ( )
{
fraction f1, f2(2L,0L);
fraction f3(f2);
f1.print();
f2.print();
f3.print();
f3 = f3 + fraction (-5 , 4);
f1 = f2 + f3;
f1.print ( );
f1 = f2 - f3;
f1.print();
f1 = f2 * f3;
f1.print();
(++ (++f1)).print();
f1 = f2 / f3;
f1.print();
f1 = 5 + f1;
f1.print();
return 0;
}
All of your operators take their parameters as references to non-const fraction. Which means they can only be called with non-const lvalues of type fraction. A temporary (such as the result of fraction(-5, 4)) is an rvalue, not an lvalue, and thus cannot be used as an argument to your operators.
I dare say it's wrong for arithmetic operators to take non-const references as parameters: that indicates they will modify their operands, which is plain wrong. You should change all the binary operators' parameters from fraction & to const fraction &.
A reference to const allows rvalues to bind it to, so your code will work as expected.
Of course, this doesn't apply to operator++ (that's why I mention binary operators above). ++ actually modifies its operand, so in its case, a reference to non-const is the correct approach. The same would apply to compound assignment operators such as +=.
This line is causing all the errors
f3 = f3 + fraction (-5 , 4)
You are using fraction operator +(fraction &f1 , fraction &f2); function to add an object and an anonymous object.
But anonymous object are only temporary. Read this answer.
Remove that line and your code should work.
Edit:
Might work if you change
fraction operator +(fraction &f1 , fraction &f2);
to
fraction operator +(fraction &f1 , fraction f2);
I defined a Fraction class as following, overloading the "=" & "+" operators.
I made this program as simple as possible to show the problem.
#include <iostream>
class Fraction {
private:
int nominator;
int denominator;
public:
Fraction ();
Fraction (int, int);
Fraction & operator = (Fraction &);
friend Fraction operator + (Fraction &, Fraction &);
// static function:
// find the Greatest Common Divisor of two numbers
int static GCD(int x, int y);
};
int Fraction::GCD(int x, int y) {
if (y == 0) {
return x;
} else {
return GCD (y, x % y);
}
}
Fraction::Fraction () {
nominator = NULL;
denominator = NULL;
}
Fraction::Fraction (int num_1, int num_2) {
int divisor = Fraction::GCD (num_1, num_2);
nominator = num_1 / divisor;
denominator = num_2 / divisor;
}
Fraction & Fraction::operator = (Fraction &A) {
nominator = A.nominator;
denominator = A.denominator;
return *this;
}
Fraction operator + (Fraction &A, Fraction &B) {
int nominator = A.nominator * B.denominator + B.nominator * A.denominator;
int denominator = A.denominator * B.denominator;
int divisor = Fraction::GCD (nominator, denominator);
return Fraction (nominator / divisor, denominator / divisor);
}
And in the Main() function, I have three test case
int main(int argc, const char * argv[]) {
Fraction frac_a = Fraction(1, 3);
Fraction frac_b = Fraction(1, 4);
// test 1: no compile error
frac_a + frac_b;
frac_a = frac_b;
// test 2: no compile error
Fraction frac_c = frac_a + frac_b;
// test 3: Error: No viable overloaded '='
Fraction frac_d;
frac_d = frac_a + frac_b;
return 0;
}
The question is, why "test 3" has "No viable overloaded '='" error?
Your assignment operator is declared to take a reference to a non-const Fraction. Your addition operator returns by-value, so you are trying to assign a temporary to frac_c. Temporaries can not bind to non-const references.
The fix is to make your assignment operator take by const-reference:
Fraction & operator = (const Fraction &);
That's because your operator= can't bind to temporaries.
You should define it like this:
Fraction & Fraction::operator = (const Fraction &A)
so, it will bind to temporaries and constant objects and literals.
You defined the assignment operator= to take an lvalue reference as argument, but tried to pass it a temporary. Temporaries only bind to const references or rvalue references.
You should read up on how to overload operators in a usable way, e.g. the same problem occurs with the nonconst lvalue references accepted by your operator+.
That means, use Fraction& operator=(Fraction const&) and Fraction operator+(Fraction const&, Fraction const&).
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.