Reputation: 639
#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
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
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