0

I have created a Rational class and have overloaded == operator for only Rational vs Rational comparison, not Rational vs int comparison yet somehow it is working for latter case as well. Why is it working? Here's the code:

bool Rational::operator==(const Rational& r) const
{
    if(denominator == r.getDenominator())
        if(numerator == r.getNumerator())
            return true;
    else
        return false;
}

int main()
{
    Rational r(16, 8); // 16/8
    cout << boolalpha << (r == 3) << '\n'; //false
    cout << boolalpha << (r == 2) << '\n'; //Why this returns "true" without knowing how to compare Rational with int?!
    return 0;
}

"r == 2" is returning true and "r == 3" false, yet "== operator" is overloaded for class vs class comparison only... here's all of the code:

#include <iostream> 
#include <cstdlib>
using namespace std;

class Rational {
public:
    Rational( int nume, int denom );
    Rational( int nume );
    void setNumeDenom( int nume, int denom );
    bool operator==( const Rational& r ) const;

    int getNumerator() const { return numerator; }
    int getDenominator() const { return denominator; }

private:
    int numerator;
    int denominator;
};

int greatestCommonDivisor( int a, int b )
{
    if( b == 0 )
        return a;   
    return greatestCommonDivisor(b, a % b); 
}

Rational::Rational( int n, int d )
{
    setNumeDenom( n, d );
}

Rational::Rational( int n )
{
    setNumeDenom( n, 1 );
}

void Rational::setNumeDenom( int n, int d )
{
    int gcd = greatestCommonDivisor(n ,d);
    if( d != 0 && gcd > 0 )
    {
        numerator = n / gcd;
        denominator = d / gcd;
    }
    else
    {
        cout << "denominator cannot be Zero.\n";
        abort();
    }
}
bool Rational::operator==(const Rational& r) const
{
    if(denominator == r.getDenominator())
        if(numerator == r.getNumerator())
            return true;
    else
        return false;
}

int main()
{
    Rational r(16, 8);
    cout << boolalpha << (r == 2) << '\n'; //true
    cout << boolalpha << (r == 3) << '\n'; //false
    return 0;
}
mhm
  • 313
  • 1
  • 5
  • 12
  • 9
    `Rational( int nume );` is a converting constructor. – ecatmur Aug 09 '17 at 10:27
  • 4
    Also note that your operator== does not always return a value: despite your indentation, the `else` belongs to the inner `if`. – CompuChip Aug 09 '17 at 10:28
  • @ecatmur Thanks! I just deleted that constructor and got compiler error for that comparison.. I did not know that thanks – mhm Aug 09 '17 at 10:30
  • 3
    Say `explicit Rational( int nume );` to prevent this conversion from taking place. – Henri Menke Aug 09 '17 at 10:30
  • @CompuChip why? if I do not use { } for if, shouldn't compiler only read the last sentence as the control condition for that if? – mhm Aug 09 '17 at 10:32
  • 2
    @mhm no the `else` belongs to the last `if` occuring before. I would always use brackets to avoid such errors. With brackets you can always add or remove statements without accidentally changing the logic of the `if-else` – 463035818_is_not_an_ai Aug 09 '17 at 10:33
  • 2
    You should increase your warning level, then your compiler would warn about the *dangling-else*. – Jonas Aug 09 '17 at 10:35
  • 2
    You can avoid the whole dangling if-else chain if you take a moment to ponder this: You want to return the boolean value of `denominator == r.getDenominator() && numerator == r.getNumerator()`. So do just that `return denominator == r.getDenominator() && numerator == r.getNumerator();` – StoryTeller - Unslander Monica Aug 09 '17 at 10:37
  • 1
    @mhm indeed, so the control condition for `if(denominator == r.getDenominator())` is the last "sentence": `if(numerator == r.getNumerator()) return true; else return false;`. Personally I tend to avoid this problem altogether by just always using {braces}. – CompuChip Aug 09 '17 at 10:45
  • Here's a much cleaner way to write that test: `return numerator == r.numerator && denominator == r.denominator;`. No dangling elses. – Pete Becker Aug 09 '17 at 12:13

0 Answers0