user2757842
user2757842

Reputation: 639

operator overloading Fractions

#include"Fraction.h"

#include<iostream>

using namespace std;


Fraction operator*(const Fraction& left, const Fraction& right)
{
    int newNum = left.getNum() * right.getNum();
    int newDenom = right.getDenom() * left.getDenom();

    Fraction result(newNum, newDenom); //Error is here, cannot convert from Fraction to int
    return result;
}

int main()
{
    Fraction a(3,4);
    Fraction b(1,2);
    Fraction c = a * b;

    cout << c << endl;
}

This is my code here, we just started doing operator overloads this week and I'm quite stuck.

The main obviously does not work but that's the input I want to pass through, but I don't understand the error I'm getting. Can anyone break this down for me just a little? I'd appreciate it.

//This is my Header file for anyone that wants to see it

#ifndef FRACTION_H
#define FRACTION_H

class Fraction
{

public:

    Fraction(int numParam, int denomParam);

    void setNum(int numParam);
    int getNum() const;

    void setDenom(int denomParam);
    int getDenom() const;

private:
    int num;
    int denom;

};

#endif

Upvotes: 2

Views: 4429

Answers (2)

Dennington-bear
Dennington-bear

Reputation: 1782

ok I think I know what the problem was. In the header file the constructor was not defined so that when he ran the program it would not pick up that the fraction class took in two ints. Therefore by defining the constructor the program was allowed to run!

Basically this was not in it.

Fraction::Fraction(int numeratorParam, int denomeratorParam)
{

numerator = numeratorPram;

denumerator = denumeratorParam;

}

Upvotes: 1

Alec Teal
Alec Teal

Reputation: 5928

It doesn't know how to display fractions, add this:

std::ostream& operator<<(std::ostream& stream, const Fraction& frac) {
    stream<<"Do something with frac here, like output num/denom\n";
    return stream;
}

Although it isn't whining about your cout line now, it will when you fix this error, because it doesn't know how to do a << on a std::ostream and a Fraction.

NOT THIS - from original answer

Your error is likely one of those "used from here" error markers, it's telling you where it got confused, it probably tried to print frac as an int.... yeah.

ACTUAL ANSWER

When you say Fraction A = B*C; the compiler sees something like Fraction A = AnotherFraction; it can do Fraction A; (default constructor) followed by Fraction::operator=(Fraction&); or it could use r-values in this case (move assignments) from the temporary you return.

C++ allows one level of implicit casting, somewhere you have "Fraction::Fraction(int);" - a constructor that takes an int, C++ wants to convert your Fraction to an int, and construct a new Fraction with that int.

it is whining because it can't. Give it a copy constructor, see rule of 3 (now rule of 5), you should always have your assignment operator and copy constructor, never just one (without VERY good reason) and with C++11 your assignment r-value operator and "" constructor.

In closing

we need your constructors, that one level of implict casting is giving you errors that appear weird because "why int" but for some reason C++ wants to use Fraction::Fraction(int), which I know exist from what you've said, it's upset because it can't go fraction->int (it wants to do fraction->int->fraction)

Note

This is why C++ has a heavy learning curve, because it is so powerful (what it does with implict conversions is without a doubt a good thing!) you can get errors that tell you more where it got confused than what is actually wrong. Like when you have an operator<< with a typo and it tries to match it to one of the standard operator<<, you get like a 4 page reason about why what you said is wrong and how it can't instantiate a certain (unrelated in a human's view) template.

Addendum

template<class T>
class Ratio {
public:
    Ratio(): top(0), bottom(1) {}
    Ratio(T& from): top(from), bottom(1) {}
    Ratio(T& top, T& bottom): top(top), bottom(bottom) {}
    Ratio(T&& from): top(from), bottom(1) {}
    Ratio(T&& top, T&& bottom): top(top), bottom(bottom) {}
    Ratio& operator=(Ratio& from) {
        top = from.top;
        bottom = from.bottom;
    }
    Ratio& operator=(Ratio&& from) {
        top = from.top;
        bottom = from.bottom;
    }
    Ratio(const Ratio& from): top(from.top), bottom(from.bottom) {}
    Ratio(Ratio&& from): top(from.top), bottom(from.bottom) {}
    ~Ratio() {}

    const T& getTop() const { return top; }
    const T& getBottom() const { return bottom; }
    T& getTop() { return top; }
    T& getBottom() { return bottom; }


    Ratio operator*(const Ratio& rhs) const { //we are the left hand side
        T newTop = rhs.top*this->top;
        T newBottom = rhs.bottom*this->bottom;
        Ratio result(newTop,newBottom);
        return result;
    }
private:
    T top;
    T bottom;
};

template<class T>
std::ostream& operator<<(std::ostream& stream, const Ratio<T>& ratio) {
    stream<<ratio.getTop()<<"/"<<ratio.getBottom();
    return stream;
}

typedef Ratio<int> Fraction;

int main(int,char**) {
    Fraction a;
    std::cout<<"A: "<<a<<"\n";
    Fraction b(1);
    std::cout<<"B: "<<b<<"\n";
    Fraction c = a*b;
    std::cout<<"A*B=C: "<<c<<"\n";
    Fraction d(5,3);
    std::cout<<"Look! "<<d*d<<"\n";
    return 0;
}

That works!

Upvotes: 3

Related Questions