1

I've asked a similar question before (Why the code doesn't work on CodeBlocks,but on VS works).
Now a new error confused me.

cout << ++a1 << endl; will call the function operator double().

If in the code Fraction& operator++() I remove the & to make it Fraction operator++(), it will call the ostream& operator<<(ostream& os, Fraction&& obj).

#include <iostream>
using namespace std;
class Fraction
{
private:
    int fenzi, fenmu;
public:
    Fraction(int a, int b) :fenzi(a), fenmu(b) {}
    operator double()
    {
        return 1.0* fenzi / fenmu;
    }
    friend ostream& operator<<(ostream& os,  Fraction&& obj)
    {
        os << obj.fenzi << "/" << obj.fenmu;
        return os;
    }
    Fraction& operator++()
    {
        fenzi++;
        fenmu++;
        return *this;
    }
    Fraction operator++(int)
    {
        Fraction tmp(fenzi, fenmu);
        fenzi++;
        fenmu++;
        return tmp;
    }
};
int main()
{
    Fraction a1(9, 11), a2(1, 2);
    cout << double(a2) << endl;
    cout << ++a1 << endl;
    cout << a1++ << endl;
    return 0;
}

I wonder why is the output different?

Fraction operator++() and Fraction& operator++(), the former returns a copied one, and the latter returns the original one. But their types are both Fraction. I think it should have both called ostream& operator<<(ostream& os, Fraction&& obj).

Fraction operator++() output(I expected):

0.5
10/12
10/12

Fraction& operator++() output:

0.5
0.833333
10/12

1 Answers1

1
operator double()
{
    return 1.0* fenzi / fenmu;
}

Is the implicit conversion operator. Adding the explicit keyword to the operator double() will help with this because the compiler won't implicitly convert a Fraction into a double without you explicitly casting it into a double. The addition would look like:

explicit operator double()
{
    return 1.0* fenzi / fenmu;
}

The correct output stream operator is defined as
friend ostream& operator<<(ostream& os, Fraction& obj).
You defined it as
friend ostream& operator<<(ostream& os, Fraction&& obj)

Fraction&& is a rvalue reference instead of a lvalue reference (Fraction&). The compiler used the implicit conversion operator because the operator++ (in either definition) returns a lvalue (reference) instead of a rvalue reference which was defined as the parameter of the output stream operator.

Tarick Welling
  • 3,119
  • 3
  • 19
  • 44
  • The bit shift operator might technically be the same as the streams use for output, but their use dictates that they be declared differently. Notably, the first argument can't really be `const` and the return type must be a reference type. – François Andrieux May 14 '19 at 14:12
  • how can i add the explicit keyword to the operator double() ?and in conclusion Fraction& return a l-value,Fraction return a r-value,right? – user7476499 May 14 '19 at 14:56