Overloading << and >> operators: The program compiles but running it doesn't accept input

Viewed 49

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?

2 Answers

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&.

Related