C++ Fractions Class - c++

I have to create a class called Fractions with 2 private fields Numerator, Denominator. And a public constructor that sets Numerator and Denominator to 1 by default. I have included 4 members functions in my my Fractions class: Sum, Difference, Product, Division.
Then I am not sure what to do next. Why does book show fraction equivalences? What do I have to do with that? I guess a very important question would be what parameters should my member functions take?
Also what would be a good way to prohibit denominator of 0? Throw exception or force it to be equal to 1?
Here is the complete source code for the question #5 and #6 (not shown) after struggling with the problem for days. Questions #6 just asks to implement the greatest common divisor function to return fraction in a simplified form. So here it is...
If you think there is a way to optimize this code I'd be happy to hear your responses!
#include <iostream>
using namespace std;
class Fraction
{
private:
int numerator, denominator;
public:
Fraction()
{
numerator = 1;
denominator = 1;
}
Fraction(int n, int d)
{
numerator = n;
if (d==0)
{
cout << "ERROR: ATTEMPTING TO DIVIDE BY ZERO" << endl;
exit(0); // will terminate the program if division by 0 is attempted
}
else
denominator = d;
}
/*In the following functions I am dividing both numerator and denominator by the gcd function.
GCD function accepts both numerator and denominator values. If we had 2 fractions, 1/2 and 1/4
and we passed it into the Sum, the result would be n=6 and d=8. These are the values that GCD
function will accept, find greatest common divisor and return the integer value of 2. In my case
am diving both numerator and denominator on the same line by the greatest common divisor. Although
it probably would be more efficient to create a local int variable and store GCD value in it, but
for such small program it shouldn't make any difference.*/
Fraction Sum(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator+otherFraction.numerator*denominator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Difference(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator-otherFraction.numerator*denominator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Product(Fraction otherFraction)
{
int n = numerator*otherFraction.numerator;
int d = denominator*otherFraction.denominator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
Fraction Division(Fraction otherFraction)
{
int n = numerator*otherFraction.denominator;
int d = denominator*otherFraction.numerator;
return Fraction(n/gcd(n,d),d/gcd(n,d));
}
// I got the GCD algorithm from the following source:
// Source C#: http://www.ww.functionx.com/csharp2/examples/gcd.htm
int gcd(int n, int d)
{
int remainder;
while (d != 0)
{
remainder = n % d;
n = d;
d = remainder;
}
return n;
}
void show() // Display method
{
if (denominator == 1) // e.g. fraction 2/1 will display simply as 2
cout << numerator << endl;
else
cout << numerator << "/" << denominator << endl;
}
};
int main()
{
Fraction a(1,2);
Fraction b(1,4);
Fraction c;
c = a.Sum(b); // Result: 3/4
c.show();
c = a.Difference(b); // Result: 1/4
c.show();
c = a.Product(b); // Result: 1/8
c.show();
c = a.Division(b); // Result: 2
c.show();
return 0;
}

You may want to start with just the first part, create the class with two constructors, one if they give the two numbers, and one that defaults to 1.
Then, write the four functions, the assignment is nice enough to give you the equations.
If a denominator is ever equal to zero then I would throw an exception, as that is something the user may be able to fix. If you can show what led to it being zero, for example, if they divide (1/2)/(0/4) then your denominator is zero, which should be an error condition.
One issue you will want to look at is if this will be immutable, so, if I have (1/2) and (2/3) and I do an operation, it should return a new number, not modify either of the two that I passed in. In that case your check is always in the constructor for a zero, but you should explain which operation led to this error.

Also what would be a good way to prohibit denominator of 0? Throw exception or force it to be equal to 1?
That's completely a style question, with no provably correct answer...
But... I'd go with an exception. Again, this is just style. Changing the value silently would be carrying on silently forward having done something other than what the caller asked for.
Another alternative would be to allow 0 denominator, but have a way to inform the user that the current overall value, a/b, is NaN or infinity, or whatever "special value" you care to define.
In any case, document it carefully, so a user of the class can make informed choices.

Your fraction constructor should take a numerator and a denominator as parameters (or a whole number). The entire problem could be solved easily with operator overloading.
And yes, the best way to handle failed constructors is via exceptions. Don't forget to throw the same division_by_zero exception when you're dividing two fractions and the numerator of the denominator is zero.

Your methods could be (assuming your class is named "Fraction"):
Fraction Fraction::sum(Fraction &otherFraction)
Fraction Fraction::difference(Fraction &otherFraction)
Fraction Fraction::product(Fraction &otherFraction)
Fraction Fraction::division(Fraction &otherFraction)
(Using the method names you described - I might go for something different)
Each of these would return a new Fraction object containing the result.
You'd be into bonus points for using operator overloading and re-defining what + - / * meant.

So many questions in one question! Let me answer one (pair) for you:
Why does book show fraction
equivalences? What do I have to do
with that?
Consider this usage of your Fraction class:
TEST(FractionsAreEquivalent)
{
const Fraction one_over_two(1, 2); // 0.5
const Fraction two_over_four(2, 4); // 0.5
const bool equivalent = (one_over_two == two_over_four);
CHECK(equivalent);
}
This uses bool Fraction::operator ==(const Fraction& rhs) const.

Im a new guy so im sorry if my code looks so noob :P
#include<iostream>
using namespace std;
class Fraction
{
private :
int x;//NUMERATOR
int y;//DENOMINATOR
public :
Fraction(int tx = 0, int ty = 1)
{
if(ty == 0)
{
x = 0;
y = 1;
exit(0);
}else
{
x = tx;
y = ty;
}
}
void simplify()
{
for(int i = x; i >1;i--)
{
if(x%i == 0 && y%i == 0)
{
x = x/i;
y = y/i;
}
}
}
void Input()
{
cout<<"Input NUMERATOR: ";
cin>>x;
cout<<"Input DENOMINATOR: ";
cin>>y;
if(y==0)
{
cout<<"ERROR";
exit(0);
}
}
void Display()
{
cout<< x << "/" << y <<endl;
}
Fraction operator + (Fraction f){
Fraction temp;
temp.x = x * f.y + y * f.x;
temp.y = y * f.y;
return temp;
}
Fraction operator - (Fraction f){
Fraction temp;
temp.x = x * f.y - y * f.x;
temp.y = y * f.y;
return temp;
}
Fraction operator * (Fraction f){
Fraction temp;
temp.x = x * f.x ;
temp.y = y * f.y;
return temp;
}
Fraction operator / (Fraction f){
Fraction temp;
temp.x = x * f.y ;
temp.y = y * f.x;
return temp;
}
};
int main ()
{
Fraction f1;
f1.Input();
cout<<"Fraction: ";
f1.simplify();
f1.Display();
Fraction f2;
f2.Input();
cout<<"Fraction: ";
f2.simplify();
f2.Display();
Fraction f3,f4,f5,f6;
f3 = f1 + f2;
f4 = f1 - f2;
f5 = f1 * f2;
f6 = f1 / f2;
cout<<"Sum"<<endl;
f3.simplify();
f3.Display();
cout<<"Difference"<<endl;
f4.simplify();
f4.Display();
cout<<"Product"<<endl;
f5.simplify();
f5.Display();
cout<<"Division"<<endl;
f6.simplify();
f6.Display();
return 0;
}
Blockquote

I created a version of this Fractions class, and although my coding is terrible, it should work. Note that I defined the <=> operator, which is introduced in C++20, and defines <, >, <=, >= automatically. If you don't have that, you could use std::rel_ops or just defining them all one by one.
Fraction.h:
#include <memory>
#include <numeric>
#include <string>
class Fraction
{
private:
long long num{ 1 };
long long denom{ 1 };
inline void simplify() {
auto gcd{ std::make_unique<long long>(std::gcd(num, denom)) };
num /= *gcd;
denom /= *gcd;
gcd.reset();
if (denom < 0) {
num = -num;
denom = -denom;
}
}
public:
Fraction(double numerator = 1, double denominator = 1);
Fraction(double numerator, double denominator, int integer_part);
Fraction(const Fraction& f);
long long numerator() const;
long long denominator() const;
auto setnumerator(long long nv);
auto setdenominator(long long nv);
double value() const;
Fraction reciprocal() const;
std::string str(size_t mode = 0) const;
bool operator==(const Fraction& f) const;
auto operator<=>(const Fraction& f) const;
bool operator==(size_t s) const;
auto operator<=>(size_t s) const;
friend bool operator== (size_t s, Fraction& f);
friend auto operator<=> (size_t s, Fraction& f);
bool operator==(double d) const;
auto operator<=>(double d) const;
friend bool operator== (double d, Fraction& f);
friend auto operator<=> (double d, Fraction& f);
Fraction operator+(const Fraction& f) const;
Fraction operator+(size_t s) const;
Fraction operator+(double d) const;
friend Fraction operator+(size_t s, const Fraction& f);
friend Fraction operator+(double d, const Fraction& f);
Fraction operator-(const Fraction& f) const;
Fraction operator-(size_t s) const;
Fraction operator-(double d) const;
friend Fraction operator-(size_t s, const Fraction& f);
friend Fraction operator-(double d, const Fraction& f);
Fraction operator*(const Fraction& f) const;
Fraction operator*(size_t s) const;
Fraction operator*(double d) const;
friend Fraction operator*(size_t s, const Fraction& f);
friend Fraction operator*(double d, const Fraction& f);
Fraction operator/(const Fraction& f) const;
Fraction operator/(size_t s) const;
Fraction operator/(double d) const;
friend Fraction operator/(size_t s, const Fraction& f);
friend Fraction operator/(double d, const Fraction& f);
Fraction operator%(const Fraction& f) const;
Fraction operator%(size_t s) const;
Fraction operator%(double d) const;
friend size_t operator%(size_t s, const Fraction& f);
friend double operator%(double d, const Fraction& f);
Fraction& operator+=(const Fraction& f);
Fraction& operator+=(size_t s);
Fraction& operator+=(double d);
friend size_t operator+=(size_t s, Fraction& f);
friend double operator+=(double d, Fraction& f);
Fraction& operator-=(const Fraction& f);
Fraction& operator-=(size_t s);
Fraction& operator-=(double d);
friend size_t operator-=(size_t s, Fraction& f);
friend double operator-=(double d, Fraction& f);
Fraction& operator*=(const Fraction& f);
Fraction& operator*=(size_t s);
Fraction& operator*=(double d);
friend size_t operator*=(size_t s, Fraction& f);
friend double operator*=(double d, Fraction& f);
Fraction& operator/=(const Fraction& f);
Fraction& operator/=(size_t s);
Fraction& operator/=(double d);
friend size_t operator/=(size_t s, Fraction& f);
friend double operator/=(double d, Fraction& f);
Fraction& operator%=(const Fraction& f);
Fraction& operator%=(size_t s);
Fraction& operator%=(double d);
friend size_t operator%=(size_t s, Fraction& f);
friend double operator%=(double d, Fraction& f);
Fraction& operator++();
Fraction operator++(int);
Fraction& operator--();
Fraction operator--(int);
Fraction operator+();
Fraction operator-();
long long operator[](int i);
};
Fraction.cpp:
#include "Fraction.h"
#include <limits>
#include <sstream>
Fraction::Fraction(double numerator, double denominator)
{
double tsn{ numerator }, tsd{ denominator };
while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
tsn *= 10;
tsd *= 10;
}
num = tsn;
denom = tsd;
simplify();
}
Fraction::Fraction(double numerator, double denominator, int integer_part)
{
numerator += denominator * integer_part;
double tsn{ numerator }, tsd{ denominator };
while ((static_cast<long long>(tsn) != tsn || static_cast<long long>(tsd) != tsd) && std::numeric_limits<long long>::max() / 10 > tsn && std::numeric_limits<long long>::max() / 10 > tsd) {
tsn *= 10;
tsd *= 10;
}
num = tsn;
denom = tsd;
simplify();
}
Fraction::Fraction(const Fraction& f)
{
num = f.numerator();
denom = f.denominator();
}
long long Fraction::numerator() const
{
return num;
}
long long Fraction::denominator() const
{
return denom;
}
auto Fraction::setnumerator(long long nv)
{
num = nv;
simplify();
return this;
}
auto Fraction::setdenominator(long long nv)
{
denom = nv;
simplify();
return this;
}
double Fraction::value() const
{
return static_cast<double>(num) / denom;
}
Fraction Fraction::reciprocal() const
{
return Fraction(denom, num);
}
std::string Fraction::str(size_t mode) const
{
std::stringstream ss;
if (mode == 0) {
ss << num;
if (denom != 1) {
ss << '/' << denom;
}
}
else {
if (num % denom == 0 || denom == 1) {
ss << num / denom;
}
else {
if (abs(denom) > abs(num)) {
ss << num << '/' << denom;
}
else if (num < 0) {
ss << '-' << '(' << (num / denom) << ' ' << -(num % denom) << '/' << denom << ')';
}
else {
ss << (num / denom) << ' ' << num % denom << '/' << denom;
}
}
}
return ss.str();
}
bool Fraction::operator==(const Fraction& f) const
{
return value() == f.value();
}
auto Fraction::operator<=>(const Fraction& f) const
{
return value() <=> f.value();
}
bool Fraction::operator==(size_t s) const
{
return value() == s;
}
auto Fraction::operator<=>(size_t s) const
{
return value() <=> s;
}
bool operator==(size_t s, const Fraction& f)
{
return s == f.value();
}
auto operator<=>(size_t s, const Fraction& f)
{
return s <=> f.value();
}
bool Fraction::operator==(double d) const
{
return value() == d;
}
auto Fraction::operator<=>(double d) const
{
return value() <=> d;
}
bool operator==(double d, Fraction& f)
{
return f.value() == d;
}
auto operator<=>(double d, Fraction& f)
{
return f.value() <=> d;
}
Fraction Fraction::operator+(const Fraction& f) const
{
return Fraction(num * f.denominator() + f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator+(size_t s) const
{
return Fraction(s * denom + num, denom);
}
Fraction Fraction::operator+(double d) const
{
return *this + Fraction(d);
}
Fraction operator+(size_t s, const Fraction& f)
{
return f + s;
}
Fraction operator+(double d, const Fraction& f)
{
return f + d;
}
Fraction Fraction::operator-(const Fraction& f) const
{
return Fraction(num * f.denominator() - f.numerator() * denom, denom * f.denominator());
}
Fraction Fraction::operator-(size_t s) const
{
return Fraction(num - (s * denom), denom);
}
Fraction Fraction::operator-(double d) const
{
return *this - Fraction(d);
}
Fraction operator-(size_t s, const Fraction& f)
{
return Fraction(s * f.denom - f.num, f.denom);
}
Fraction operator-(double d, const Fraction& f)
{
return Fraction(d) - f;
}
Fraction Fraction::operator*(const Fraction& f) const
{
return Fraction(num * f.numerator(), denom * f.denominator());
}
Fraction Fraction::operator*(size_t s) const
{
return Fraction(num * s, denom);
}
Fraction Fraction::operator*(double d) const
{
return Fraction(num * d, denom);
}
Fraction operator*(size_t s, const Fraction& f)
{
return Fraction(f.numerator() * s, f.denominator());
}
Fraction operator*(double d, const Fraction& f)
{
return Fraction(f.numerator() * d, f.denominator());
}
Fraction Fraction::operator/(const Fraction& f) const
{
return (*this) * f.reciprocal();
}
Fraction Fraction::operator/(size_t s) const
{
return Fraction(num, denom * s);
}
Fraction Fraction::operator/(double d) const
{
return Fraction(num, denom * d);
}
Fraction operator/(size_t s, const Fraction& f)
{
return s * f.reciprocal();
}
Fraction operator/(double d, const Fraction& f)
{
return d * f.reciprocal();
}
Fraction Fraction::operator%(const Fraction& f) const
{
return ((*this) / f).value() > 0 ? Fraction((*this) - (floor(((*this) / f).value()) * f)) : Fraction((*this) - (ceil(((*this) / f).value()) * f));
}
Fraction Fraction::operator%(size_t s) const
{
return ((*this) / s).value() > 0 ? Fraction((*this) - (floor(((*this) / s).value()) * s)) : Fraction((*this) - (ceil(((*this) / s).value()) * s));
}
Fraction Fraction::operator%(double d) const
{
return ((*this) / d).value() > 0 ? Fraction((*this) - (floor(((*this) / d).value()) * d)) : Fraction((*this) - (ceil(((*this) / d).value()) * d));
}
size_t operator%(size_t s, const Fraction& f)
{
return (f / s).value() > 0 ? ((f) - (floor((s / f).value()) * f)).value() : ((f)-(ceil((s / f).value()) * f)).value();
}
double operator%(double d, const Fraction& f)
{
return (f / d).value() > 0 ? ((f)-(floor((d / f).value()) * f)).value() : ((f)-(ceil((d / f).value()) * f)).value();
}
Fraction& Fraction::operator+=(const Fraction& f)
{
*this = *this + f;
return *this;
}
Fraction& Fraction::operator+=(size_t s)
{
*this = *this + s;
return *this;
}
Fraction& Fraction::operator+=(double d)
{
*this = *this + d;
return *this;
}
size_t operator+=(size_t s, Fraction& f)
{
s += round(f.value());
return s;
}
double operator+=(double d, Fraction& f)
{
d += f.value();
return d;
}
Fraction& Fraction::operator-=(const Fraction& f)
{
*this = *this - f;
return *this;
}
Fraction& Fraction::operator-=(size_t s)
{
*this = *this - s;
return *this;
}
Fraction& Fraction::operator-=(double d)
{
*this = *this - d;
return *this;
}
size_t operator-=(size_t s, Fraction& f)
{
s -= round(f.value());
return s;
}
double operator-=(double d, Fraction& f)
{
d -= f.value();
return d;
}
Fraction& Fraction::operator*=(const Fraction& f)
{
*this = *this * f;
return *this;
}
Fraction& Fraction::operator*=(size_t s)
{
*this = *this * s;
return *this;
}
Fraction& Fraction::operator*=(double d)
{
*this = *this * d;
return *this;
}
size_t operator*=(size_t s, Fraction& f)
{
s *= round(f.value());
return s;
}
double operator*=(double d, Fraction& f)
{
d *= f.value();
return d;
}
Fraction& Fraction::operator/=(const Fraction& f)
{
*this = *this / f;
return *this;
}
Fraction& Fraction::operator/=(size_t s)
{
*this = *this / s;
return *this;
}
Fraction& Fraction::operator/=(double d)
{
*this = *this / d;
return *this;
}
size_t operator/=(size_t s, Fraction& f)
{
s /= round(f.value());
return s;
}
double operator/=(double d, Fraction& f)
{
d /= f.value();
return d;
}
Fraction& Fraction::operator%=(const Fraction& f)
{
*this = *this % f;
return *this;
}
Fraction& Fraction::operator%=(size_t s)
{
*this = *this % s;
return *this;
}
Fraction& Fraction::operator%=(double d)
{
*this = *this % d;
return *this;
}
size_t operator%=(size_t s, Fraction& f)
{
s = s % f;
return s;
}
double operator%=(double d, Fraction& f)
{
d = d % f;
return d;
}
Fraction& Fraction::operator++()
{
this->num += this->denom;
return *this;
}
Fraction Fraction::operator++(int)
{
Fraction copy{ *this };
this->num += this->denom;
return copy;
}
Fraction& Fraction::operator--()
{
this->num -= this->denom;
return *this;
}
Fraction Fraction::operator--(int)
{
Fraction copy{ *this };
this->num -= this->denom;
return copy;
}
Fraction Fraction::operator+()
{
return *this;
}
Fraction Fraction::operator-()
{
return Fraction(-num, denom);
}
long long Fraction::operator[](int i)
{
return i == 0 ? num : denom;
}
Most of the bottom ones are just operator overloads of different types as I was going to use the operators on Fraction objects, size_t and double objects. This should be more optimized as it has a simplify() function that is used and instead of functions like sum and difference, I used operator overloading. Fraction.str() is a bit more optimized than above. As for the zero division thing, I think that it will get caught and the compiler will at least issue a warning and when running, it should give a floating point error. If you found any bugs in the code, please comment below!

Related

Writing a fraction class and I cannot figure out these errors

I'm writing a fraction.cpp and fraction.h that inputs fraction types and does mathematical operations on them. I have a weird error that says "undefined reference", but the reference is defined as far as I can see. There's also a bunch of errors that say "no matching function for call to fraction::outputFormat(fracForm)" and "candidate is" and others. Here is all of my code for reference:
main.cpp
#include <iostream>
#include <iomanip>
using namespace std;
#include "fraction.h"
int main()
{
fraction f0;
fraction f1;
cin >> f0; // input format numerator/denominator, ex 23/9
cout << "input: " << f0 << endl; // outputs what was input
// Note the << and >> operators should also work for file streams
// cin >> f0 >> f1; // reads 2 fractions, ex 8/5 12/16
f1.setFraction(17,6); // 17/6
cout << f1.getNumerator() << '/' << f1.getDenominator() << endl; // 17/6
f1.setFraction(-4.75); // -19/4
cout << f1.decimalValue() << endl; // outputs -4.75
fraction f2(4,8); // 4/8
fraction f3(2.875); // 2 7/8
cout << f3 << endl; // outputs 2 7/8 (the default output format is mixed)
cout << f2 << endl; // outputs 4/8
fraction f4(16,8);
cout << f4 << endl; // outputs 2
fraction::outputFormat(improper); // set output format to improper fraction
cout << f4 << endl; // outputs 16/8
cout << f3 << endl; // outputs 23/8
cout << f1 << endl; // outputs -19/4
fraction::outputFormat(decimal); // set output format to decimal value
cout << f3 << endl; // outputs 2.875
cout << f2 << endl; // outputs 0.5
cout << f1 << endl; // outputs -4.75
fraction::outputFormat(mixed); // set output format back to default mixed
cout << f3 << endl; // outputs 2 7/8
f1.setFraction(-4.75);
cout << f1 << endl; // outputs -4 3/4
cout << f2 << endl; // outputs 4/8
fraction f5(12,8);
fraction::outputFormat(improper);
cout << f5 << endl; // outputs 12/8
f2.reduce(); // convert to lowest terms
f5.reduce();
cout << f2 << endl; // outputs 1/2
cout << f5 << endl; // outputs 3/2
f5.setDenominator(16); // change denominator and numerator
// error if numerator is not a whole number
cout << f5 << endl; // outputs 24/16
f5.setDenominator(22);
cout << f5 << endl; // outputs 33/22
f5.setDenominator(5); // output error as numerator would have to be 7.5
cout << f5 << endl; // outputs 33/22 (fraction remained the same)
f1 = f3+f2; // f1 put in lowest terms
cout << f1 << endl; // outputs 27/8
f1 = f3-f2;
cout << f1 << endl;
f1 = f3*f2;
cout << f1 << endl;
f1 = f3/f2;
cout << f1 << endl;
f1 = f3;
cout << f1 << endl; // outputs 23/8
f1 = 7.75;
f1 = f2 = 7.75;
cout << f1 << endl; // outputs 31/4
cout << setw(6) << f1 << setw(6) << f2 << endl; // outputs 31/4 31/4
f0.setFraction(31,4);
if (f0 == f1)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing 2 fractions
if (f0 == 7.75)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing fraction to double
f0.setFraction(2);
if (f0 < 3)
cout << "correct\n";
else
cout << "incorrect\n";
// all relational operators should work for comparing fraction to int
return 0;
}
fraction.h
#ifndef fraction
#include <iostream>
using namespace std;
enum fracForm {improper, mixed, decimal};
class fraction {
enum fracForm {improper, mixed, decimal};
friend istream& operator>>(istream&, fraction&);
friend ostream& operator<<(ostream&, fraction&);
public:
fraction();
fraction(int, int);
fraction(double);
void setFraction(int, int);
void setFraction(double);
void setDenominator(int);
int getNumerator() const;
int getDenominator() const;
double decimalValue() const;
static void outputFormat(fracForm);
void reduce();
fraction operator+(const fraction&) const;
fraction operator-(const fraction&) const;
fraction operator*(const fraction&) const;
fraction operator/(const fraction&) const;
bool operator==(const fraction&) const;
bool operator!=(const fraction&) const;
bool operator<(const fraction&) const;
bool operator>(const fraction&) const;
bool operator<=(const fraction&) const;
bool operator>=(const fraction&) const;
fraction operator+(const int) const;
fraction operator-(const int) const;
fraction operator*(const int) const;
fraction operator/(const int) const;
bool operator==(const int) const;
bool operator!=(const int) const;
bool operator<(const int) const;
bool operator>(const int) const;
bool operator<=(const int) const;
bool operator>=(const int) const;
fraction operator+(const float) const;
fraction operator-(const float) const;
fraction operator*(const float) const;
fraction operator/(const float) const;
bool operator==(const float) const;
bool operator!=(const float) const;
bool operator<(const float) const;
bool operator>(const float) const;
bool operator<=(const float) const;
bool operator>=(const float) const;
fraction operator+(const double) const;
fraction operator-(const double) const;
fraction operator*(const double) const;
fraction operator/(const double) const;
bool operator==(const double) const;
bool operator!=(const double) const;
bool operator<(const double) const;
bool operator>(const double) const;
bool operator<=(const double) const;
bool operator>=(const double) const;
string mix();
private:
int num, denom;
static fracForm format;
};
#endif
fraction.cpp
#include "fraction.h"
#include <iostream>
#include <algorithm>
fraction::fraction() {
num = 0;
denom = 1;
}
fraction::fraction(int numerator, int denominator) {
setFraction(numerator, denominator);
}
fraction::fraction(double deci) {
setFraction(deci);
}
void fraction::setFraction(int numerator, int denominator){
num = numerator;
denom = denominator;
}
void fraction::setFraction(double deci) {
int decimal = deci;
denom = 1;
while (deci != decimal) {
deci = deci * 10;
denom = denom * 10;
decimal = deci;
}
num = deci;
reduce();
}
void fraction::setDenominator(int denominator) {
int denom2 = denominator;
int proportion = num * denom2;
double newProp = proportion / denom;
int intProp = newProp;
if (newProp != intProp) {
try
{
throw 20;
}
catch (int n)
{
cout << "This does not create a fraction with integers." << endl;
}
}
else {num = newProp; denom = denom2;}
}
int fraction::getNumerator() const {
return num;
}
int fraction::getDenominator() const{
return denom;
}
double fraction::decimalValue() const {
double deci = num/denom;
return deci;
}
void fraction::outputFormat(fracForm fType) {
format = fType;
}
void fraction::reduce() {
num = num / __gcd(num, denom);
denom = denom / __gcd(num, denom);
}
fraction fraction::operator+(const fraction& frac) const {
return fraction(decimalValue() + frac.decimalValue());
}
fraction fraction::operator-(const fraction& frac) const {
return fraction(decimalValue() - frac.decimalValue());
}
fraction fraction::operator*(const fraction& frac) const {
return fraction(decimalValue() * frac.decimalValue());
}
fraction fraction::operator/(const fraction& frac) const {
return fraction(decimalValue() / frac.decimalValue());
}
bool fraction::operator==(const fraction& frac) const {
return decimalValue() == frac.decimalValue();
}
bool fraction::operator!=(const fraction& frac) const {
return decimalValue() != frac.decimalValue();
}
bool fraction::operator<(const fraction& frac) const {
return decimalValue() < frac.decimalValue();
}
bool fraction::operator>(const fraction& frac) const {
return decimalValue() > frac.decimalValue();
}
bool fraction::operator<=(const fraction& frac) const {
return decimalValue() <= frac.decimalValue();
}
bool fraction::operator>=(const fraction& frac) const {
return decimalValue() >= frac.decimalValue();
}
fraction fraction::operator+(const int frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const int frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const int frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const int frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const int frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const int frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const int frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const int frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const int frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const int frac) const {
return decimalValue() >= frac;
}
fraction fraction::operator+(const float frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const float frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const float frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const float frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const float frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const float frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const float frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const float frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const float frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const float frac) const {
return decimalValue() >= frac;
}
fraction fraction::operator+(const double frac) const {
return fraction(decimalValue() + frac);
}
fraction fraction::operator-(const double frac) const {
return fraction(decimalValue() - frac);
}
fraction fraction::operator*(const double frac) const {
return fraction(decimalValue() * frac);
}
fraction fraction::operator/(const double frac) const {
return fraction(decimalValue() / frac);
}
bool fraction::operator==(const double frac) const {
return decimalValue() == frac;
}
bool fraction::operator!=(const double frac) const {
return decimalValue() != frac;
}
bool fraction::operator<(const double frac) const {
return decimalValue() < frac;
}
bool fraction::operator>(const double frac) const {
return decimalValue() > frac;
}
bool fraction::operator<=(const double frac) const {
return decimalValue() <= frac;
}
bool fraction::operator>=(const double frac) const {
return decimalValue() >= frac;
}
fraction::mix() {
int integer = 0;
int n = num;
while (num > denom) {
num = num - denom;
integer = integer + 1;
}
return to_string(integer) + " " + to_string(num) + "/" + to_string(denom);
}
istream& operator>>(istream& in, fraction& frac) {
in >> frac.num;
char i;
in >> i;
in >> frac.denom;
return i;
}
ostream& operator<<(ostream& out, fraction& frac) {
switch (frac.format) {
case improper:
out << to_string(frac.getNumerator()) + "/" + to_string(frac.getDenominator()); break;
case decimal:
out << frac.decimalValue(); break;
case mixed:
out << frac.mix(); break;
}
}
Here are the specific errors:
main.cpp: In function ‘int main()’:
main.cpp:27:35: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(improper); // set output format to improper fraction
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:32:34: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(decimal); // set output format to decimal value
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:37:32: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(mixed); // set output format back to default mixed
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
main.cpp:44:35: error: no matching function for call to ‘fraction::outputFormat(fracForm)’
fraction::outputFormat(improper);
^
In file included from main.cpp:4:0:
fraction.h:27:21: note: candidate: static void fraction::outputFormat(fraction::fracForm)
static void outputFormat(fracForm);
^~~~~~~~~~~~
fraction.h:27:21: note: no known conversion for argument 1 from ‘fracForm’ to ‘fraction::fracForm’
fraction.cpp:235:15: error: ISO C++ forbids declaration of ‘mix’ with no type [-fpermissive]
fraction::mix() {
^
fraction.cpp:235:1: error: prototype for ‘int fraction::mix()’ does not match any in class ‘fraction’
fraction::mix() {
^~~~~~~~
In file included from fraction.cpp:1:0:
fraction.h:69:16: error: candidate is: std::string fraction::mix()
string mix();
^~~
fraction.cpp: In function ‘std::istream& operator>>(std::istream&, fraction&)’:
fraction.cpp:250:12: error: invalid initialization of reference of type ‘std::istream& {aka std::basic_istream&}’ from expression of type ‘char’
return i;
You declare the enum fracForm two times:
enum fracForm {improper, mixed, decimal};
class fraction {
enum fracForm {improper, mixed, decimal};
The functions in class fraction are now using the enum fraction::fracForm, and the code outside (so in main.cpp) uses fracForm
These two enums aren't the same, so the code won't compile.
To solve the problem, you can use either the "global" approach, where fracForm is resolved from the fraction class:
enum fracForm {improper, mixed, decimal};
class fraction {
//enum fracForm {improper, mixed, decimal};
With that solution, I would think most errors are gone.
The other solution would be, to put the fracForm error in the fraction class scope:
//enum fracForm {improper, mixed, decimal};
class fraction {
public:
enum fracForm {improper, mixed, decimal};
Now you have to use the enum outside the class like:
fracForm type = fraction::improper;

C++ class operator overloads don't work with std::sort

So I have been been trying to build a median generator that takes in fractions and generates the median however it seems like currently I am unable to sort a vector of my self defined RationalNumber class. I have overloaded a number of the operators ( * + / == etc etc) however they don't seem to work when called inline elsewhere.
RationalNumber RationalNumber::operator*(const RationalNumber& r)
{
RationalNumber result(numerator * r.numerator, denominator * r.denominator);
result.reduceFraction();
return result;
}
RationalNumber RationalNumber::operator*(int x)
{
RationalNumber result(numerator * x, denominator);
result.reduceFraction();
return result;
}
RationalNumber RationalNumber::operator/(const RationalNumber& r)
{
RationalNumber result(numerator * r.denominator, denominator * r.numerator);
result.reduceFraction();
return result;
}
RationalNumber RationalNumber::operator/(int x)
{
RationalNumber result(numerator, denominator * x);
result.reduceFraction();
return result;
}
bool RationalNumber::operator<(const RationalNumber& r)
{
if(this->floatingPoint < r.floatingPoint)
{
return true;
}
return false;
}
bool RationalNumber::operator<(int x)
{
if(floatingPoint < (double) x)
{
return true;
}
return false;
}
bool RationalNumber::operator>(const RationalNumber& r)
{
if(floatingPoint > r.floatingPoint)
{
return true;
}
return false;
}
bool RationalNumber::operator>(int x)
{
if(floatingPoint > (double) x)
{
return true;
}
return false;
}
RationalNumber RationalNumber::operator+(const RationalNumber& r)
{
RationalNumber result((numerator * r.denominator)+(r.numerator*denominator),denominator * r.denominator);
result.reduceFraction();
return result;
}
RationalNumber RationalNumber::operator+(int x)
{
RationalNumber result(numerator * x,denominator);
return result;
}
So here I have a class that is meant to represent rational numbers with overloaded operators that are intended for the purpose of carrying out arithmetic. However when in a main class performing the following:
RationalNumber medianCalculator(std::vector<RationalNumber*> &listOfRationalNumbers)
{
std::sort(listOfRationalNumbers.begin(),listOfRationalNumbers.end());
if(!(listOfRationalNumbers.size() % 2)){
return ((RationalNumber(*listOfRationalNumbers.at((listOfRationalNumbers.size()/2) +1)) + (RationalNumber(*listOfRationalNumbers.at(listOfRationalNumbers.size()/2))) / 2));
} else {
return RationalNumber(*listOfRationalNumbers.at(listOfRationalNumbers.size() +1));
}
}
First of all, it seems to generate an out of range exception, but more importantly it seems like operator overloading hasn't worked as the std::sort call doesn't seem to work or the arithmetic.
Definitely the operators are overloaded incorrectly. For example this code would produce unexpected result:
RationalNumber num(1, 1);
num *= 2;
// num is still 1/1
The correct implementation should be:
RationalNumber& RationalNumber::operator*(int x)
{
numerator *= x;
reduceFraction();
return *this;
}
The rest of the methods should be implemented accordingly.

Call to non-static member function without an object argument

Can anyone explain this error any why I am getting it? I believe I've got all of the arithmetic down in my separate class.
This program stores and manipulates fractions, while testing overloading.
Thank you in advance.
I am trying to test this in the driver with the output looking like this.
f1 = 3/6, f2 = 4/5
f1 + f2 = 39/30 = 13/10 = 1.3
f1 - f2 = -9/30 = -3/10 = -0.3
f1 * f2 = 12/30 = 2/5 = 0.4
f1 / f2 = 15/24 = 5/8 = 0.625
Enter a fraction [numerator denominator]: 2 5
You entered 2/5
My Fraction.cpp class
#include "Fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction(const int numerator, const int denominator) { }
int Fraction::getNumerator() const {
return numerator;
}
int Fraction::getDenominator() const {
return denominator;
}
int Fraction::gcd() const {
int n = numerator;
int d = denominator;
int temp;
while (d!=0) {
temp = n % d;
n = d;
d = temp;
}
return n;
}
void Fraction::setNumerator(const int numerator) {
this->numerator = numerator;
}
void Fraction::setDenominator(const int denominator) {
this->denominator = denominator;
}
string Fraction::toString() const {
return "";
}
double Fraction::returnDecimal() const {
double a = (double) getNumerator();
double b = (double) getDenominator();
return (a / b);
}
void Fraction::reduce() {
int a = gcd();
int b = numerator / a;
int c = denominator / a;
setNumerator(b);
setDenominator(c);
}
Fraction Fraction::operator +(const Fraction& f) const {
Fraction temp;
int a = getNumerator();
int b = getDenominator();
int c = f.getNumerator();
int d = f.getDenominator();
int tempOne = b;
int tempTwo = d;
a = a * tempTwo;
b = b * tempTwo;
c = c * tempOne;
d = d * tempOne;
temp.setNumerator(a+c);
temp.setDenominator(d);
return temp;
}
Fraction Fraction::operator -(const Fraction& f) const {
Fraction temp;
int a = getNumerator();
int b = getDenominator();
int c = f.getNumerator();
int d = f.getDenominator();
int tempOne = b;
int tempTwo = d;
a = a * tempTwo;
b = b * tempTwo;
c = c * tempOne;
d = d * tempOne;
temp.setNumerator(a-c);
temp.setDenominator(d);
return temp;
}
Fraction Fraction::operator *(const Fraction& f) const {
Fraction temp;
temp.setNumerator(getNumerator() * f.getNumerator());
temp.setDenominator(getDenominator() * f.getDenominator());
return temp;
}
Fraction Fraction::operator /(const Fraction& f) const {
Fraction temp;
temp.setNumerator(getNumerator() * f.getDenominator());
temp.setDenominator(getDenominator() * f.getNumerator());
return temp;
}
bool Fraction::operator ==(const Fraction& f) const {
return ( (getNumerator() == f.getNumerator()) && (getDenominator() == f.getDenominator()) );
}
bool Fraction::operator !=(const Fraction& f) const {
return !( (getNumerator() == f.getNumerator()) && (getDenominator() == f.getDenominator()) );
}
bool Fraction::operator <(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) < (c/d));
}
bool Fraction::operator <=(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) <= (c/d));
}
bool Fraction::operator >(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) > (c/d));
}
bool Fraction::operator >=(const Fraction& f) const {
double a = getNumerator();
double b = getDenominator();
double c = getNumerator();
double d = getDenominator();
return ((a/b) >= (c/d));
}
ostream& operator <<(ostream& out, const Fraction& f) {
out << f.getNumerator() << "/" << f.getDenominator();
return out;
}
istream& operator >>(istream& in, Fraction& f) {
int a;
int b;
in >> a >> b;
f.setNumerator(a);
f.setDenominator(b);
return in;
}
My main class.
#include <iostream>
#include "Fraction.h"
#include "Fraction.cpp"
using namespace std;
int main(int argc, const char * argv[])
{
Fraction::getNumerator() const;
Fraction::getDenominator() const;
Fraction::gcd() const;
Fraction::setNumerator(<#const int numerator#>);
Fraction::setDenominator(<#const int denominator#>);
Fraction::toString();
Fraction::returnDecimal() const;
Fraction::reduce();
return 0;
}
Fraction.h
#include <iostream>
#include <string>
using namespace std;
class Fraction {
private:
int numerator;
int denominator;
int gcd() const;
public:
Fraction(const int numerator = 0, const int denominator = 0);
int getNumerator() const;
int getDenominator() const;
void setNumerator(const int numerator);
void setDenominator(const int denominator);
string toString() const;
double returnDecimal() const;
void reduce();
bool operator ==(const Fraction& f) const;
bool operator !=(const Fraction& f) const;
bool operator <(const Fraction& f) const;
bool operator <=(const Fraction& f) const;
bool operator >(const Fraction& f) const;
bool operator >=(const Fraction& f) const;
Fraction operator +(const Fraction& f) const;
Fraction operator -(const Fraction& f) const;
Fraction operator *(const Fraction& f) const;
Fraction operator /(const Fraction& f) const;
friend ostream& operator <<(ostream&, const Fraction&);
friend istream& operator >>(istream&, Fraction&);
};
Fraction is a class. You need an object of that class in order to call its (nonstatic) functions.
Fraction f;
f.getNumerator();

request for a member in which is of non class type c++

I am striving to test every function in this class and I cannot test the function that will assign a numerator and denominator to the constructor that takes no arguments here is my code. I get this error request for a member 'numerator' in 'first' which is of non class type 'Rational'
#include "Rational.h"
#include <iostream>
#include <string>
#include "GCD.h"
#include <assert.h>
using namespace std;
Rational:: Rational()
{
myNumerator = 1;
myDenominator = 1;
}
Rational:: Rational(int numerator, int denominator)
{
assert(denominator != 0);
myNumerator = numerator;
myDenominator = denominator;
reduce();
}
Rational:: Rational(const Rational &r)
{
myNumerator = r.myNumerator;
myDenominator = r.myDenominator;
}
const Rational& Rational :: operator = (const Rational &rhs)
{
if (this != &rhs)
{
myNumerator = rhs.myNumerator;
myDenominator = rhs.myDenominator;
return rhs;
}
}
int Rational:: numerator(int a) const
{
myNumerator = a;
return myNumerator;
}
int Rational:: denominator(int b) const
{
myNumerator = b;
return myDenominator;
}
void Rational:: reduce()
{
int commonDivisor = GCD(myNumerator, myDenominator);
myNumerator = myNumerator / commonDivisor;
myDenominator = myDenominator / commonDivisor;
}
Rational operator + (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator();
int denominator = lhs.denominator() * rhs.denominator();
Rational sum(numerator, denominator);
return sum;
}
Rational operator - (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator() + rhs.numerator() * lhs.denominator();
int denominator = lhs.denominator() * rhs.denominator();
Rational difference(numerator, denominator);
return difference;
}
Rational operator * (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.numerator();
int denominator = lhs.denominator() * rhs.denominator();
Rational product(numerator, denominator);
return product;
}
Rational operator / (const Rational &lhs, const Rational &rhs)
{
int numerator = lhs.numerator() * rhs.denominator();
int denominator = lhs.denominator() * rhs.numerator();
Rational product(numerator, denominator);
return product;
}
ostream& operator << (ostream & os, const Rational &r)
{
os << r.numerator() << "/" << r.denominator();
return os;
}
istream& operator >> (istream &is, Rational &r)
{
char divisionSymbol;
int numerator = 0, denominator = 0;
is >> numerator >> divisionSymbol >> denominator;
assert(divisionSymbol == '/');
assert(denominator != 0);
Rational number(numerator, denominator);
r = number;
return is;
}
#include <iostream>
#include "Rational.h"
using namespace std;
int main()
{
Rational first(), second(75, 350), third(13, 55);
Rational fourth(second);
cout << first << endl << second << endl << third << endl << fourth <<endl;
first.numerator(3)const;
first.denominator(5)const;
cout << first;
}
Rational first(); is parsed as a function declaration. it is known as Most vexing parse.
You may use Rational first;
And in C++11, you may also use Rational first{};
There is no reason to mark your functions as const if you're going to modify your member variables. It's a promise that you won't modify *this and you do so anyway. So simply remove it. You also provide const "getters" anyway.
int numerator(int a);
int numerator() const {return myNumerator;}
int denominator(int b);
int denominator() const {return myDenominator;}
int Rational:: numerator(int a)
{
// ..
}
int Rational:: denominator(int b)
{
// ..
}
Your copy assignment operator also doesn't make sense. I suggest changing it:
if (this == &rhs)
{
return *this;
}
myNumerator = rhs.numerator();
myDenominator = rhs.denominator();
return *this;
Now for the error others pointed out, your compiler happily warns that empty parentheses interpreted as a function declaration. Simply remove the parentheses or replace them with brackets {} in C++11 mode. Also, you don't need the const keyword when calling a const member function.
Rational first, second(75, 350), third(13, 55);
first.numerator(3);
first.denominator(5);

Conversion constructor won't convert "2" into user-defined-type in operator +

I have a class called Fraction :
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
using namespace std;
class Fraction
{
// data
int m_iNom;
int m_iDenom;
// operations
int gcd (int i, int j);
void reduce ();
public:
Fraction (int nn=0, int dn=1); // 1 declaration = 3 constructors
Fraction (const Fraction& fr); //C.Ctor
~Fraction (); //Dtor
Fraction& operator = (const Fraction &fr); //assignment
Fraction& operator ++ (); // prefix - ++a
const Fraction operator ++ (int); // postfix - a++
friend const Fraction operator + (const Fraction &f1, const Fraction &f2);
friend const Fraction operator - (const Fraction &f1, const Fraction &f2);
friend const Fraction operator * (const Fraction &f1, const Fraction &f2);
friend const Fraction operator / (const Fraction &f1, const Fraction &f2);
Fraction& operator += (const Fraction &f);
operator double () { return double (m_iNom) / m_iDenom; } //casting operator
friend istream& operator >> (istream &is, Fraction &f);
friend ostream& operator << (ostream &os, const Fraction &f);
const int& operator[] (int i) const;
int& operator [] (int i);
};
#endif
with the next implementation file :
#include "Fraction.h"
#include <iostream>
using namespace std;
Fraction::Fraction (int nn, int dd) :
m_iNom (nn), m_iDenom (dd) {
if (m_iDenom == 0)
m_iDenom = 1;
reduce ();
cout<<"Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
Fraction::Fraction (const Fraction & fr){
m_iNom=fr.m_iNom;
m_iDenom=fr.m_iDenom;
cout<<"C.Ctor - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
Fraction::~Fraction() {
cout<<"del: "<<m_iNom<<"/"<<m_iDenom<<endl;
}
int Fraction::gcd (int i, int j) {
if ((i == 0) || (j == 0))
return i + j;
while (i %= j) {
int t = i;
i = j;
j = t;
}
return j;
}
void Fraction::reduce () {
int g = gcd (m_iNom, m_iDenom);
m_iNom /= g;
m_iDenom /= g;
}
const Fraction operator + (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom + f1.m_iDenom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator - (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom - f1.m_iDenom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator * (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iNom;
int dd = f1.m_iDenom * f2.m_iDenom;
return Fraction (nn, dd);
}
const Fraction operator / (const Fraction &f1, const Fraction &f2) {
int nn = f1.m_iNom * f2.m_iDenom;
int dd = f1.m_iDenom * f2.m_iNom;
return Fraction (nn, dd);
}
Fraction& Fraction::operator = (const Fraction &f)
{
m_iNom = f.m_iNom;
m_iDenom = f.m_iDenom;
cout<<"OP = - Fraction: "<<m_iNom<<"/"<<m_iDenom<<endl;
return *this;
}
Fraction& Fraction::operator += (const Fraction &f) {
(*this) = (*this) + f;
return *this;
}
Fraction& Fraction::operator ++ ()
{
m_iNom += m_iDenom;
reduce ();
return *this;
}
const Fraction Fraction::operator ++ (int)
{
int nn = m_iNom;
int dd = m_iDenom;
m_iNom += m_iDenom;
reduce ();
return Fraction (nn, dd);
}
istream& operator >> (istream &is, Fraction &frac)
{
char divSign;
is >> frac.m_iNom >> divSign >> frac.m_iDenom;
if (frac.m_iDenom == 0)
frac.m_iDenom = 1;
frac.reduce ();
return is;
}
ostream& operator << (ostream& os, const Fraction &frac)
{
return os << frac.m_iNom << "/" << frac.m_iDenom;
}
int& Fraction::operator [] (int i){
cout<<"reg []"<<endl;
if (i==1)
return m_iNom;
return m_iDenom;
}
const int& Fraction::operator[] (int i) const{
cout<<"const []"<<endl;
if (i==1)
return m_iNom;
return m_iDenom;
}
and I'm trying to do the action Fraction f4=f2+2; but I get the following compiler error:
..\main.cpp:13: error: ambiguous overload for 'operator+' in 'f2 + 2'
..\main.cpp:13: note: candidates are: operator+(double, int) <built-in>
..\Fraction.h:27: note: const Fraction operator+(const Fraction&, const Fraction&)
But how could that be , if I have a conversion Constructor (please notice the Ctor in the .h file with the default values) with one argument which is suppose to convert the "2" into a Fraction ...then what's might the be the problem ?
thanks
Ronen
Edit :
here's the main file (if it would help)
#include <iostream>
using namespace std;
#include "Fraction.h"
int main() {
Fraction f1(1,2);
Fraction f2(2);
Fraction f3;
Fraction f4=f2+2; // problem's here
f2+f2;
Fraction f5=f2-f1+f4;
return 0;
}
The compiler can't decide whether to convert f2 to double then add double and int, or to construct Fraction from 2 then add two fractions.
Options:
Make operator double() explicit (C++11)
Overload operator + to take ints
Problem is:
operator double ()
defined inside your Fraction class.
While evaluating,
Fraction f4=f2+2;
Compiler has 2 choices:
First Choice:
The compiler can convert f2 to a double using your provided operator function and then it can be used to call the inbuilt operator function:
operator+(double, int);
Second Choice:
The compiler can convert 2 to a object of Fraction using constructor and then call:
const Fraction operator+(const Fraction&, const Fraction&)
The two choices cause an ambiguity and then the compiler complains and reports it to you.
Solution:
Change the name of the double operator function.
The compiler can indeed make 2 choices when you write something like f2+2.
It can first convert 2 to a fraction by using the fraction's constructor and then use the Fraction's + operator.
It can first convert f2 to a double using the Fraction's double operator, and then simply add the double and the integer
You will have to make either the constructor explicit, or give the double-operator an explicit name (e.g. toDouble) to solve the problem.