Overloading overloaded operators

2019-08-13 03:25发布

问题:

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

class binaryOperators 
{
    public:
        int i;

        binaryOperators (int tempI = 0)
        {
            i = tempI;
        }

        binaryOperators operator<< (const binaryOperators &right);
};

binaryOperators operator<< (const binaryOperators &left, const binaryOperators &right)
{
    cout << "\nOne";
    return left;
}

binaryOperators binaryOperators :: operator<< (const binaryOperators &right)
{
    cout << "\nTwo";
    return *this;
}

int main ()
{   
    binaryOperators obj;

    // Compiler's behavior: This statement calls the overloaded operator << declared inside the class.
    obj << 5 << 3 << 2;
    // Compiler's behavior: This statement calls the overloaded operator << declared outside the class.
    2 << obj;

    return 0;
}

I have written the comments inside the main() function.
What's the reason for this sort of compiler's behavior?

Is this behavior compiler dependent?

GCC on Linux

回答1:

The behavior you're seeing is caused by const-correctness. The operator<< defined within the class is non-const, so it can only operate on a non-const object or reference, such as obj. The non-member version outside the class has two constant operands.

If you wrote the member version as a non-member, it would look like this:

binaryOperators operator<< (binaryOperators &left, const binaryOperators &right)
{
    cout << "\nTwo";
    return left;
}

When overload-matching, the compiler chooses the best fit. In the first case, the left operand is non-const, so it chooses the member operator. In the second case, the left operand is an rvalue (temporary binaryOperators), which is referenced as const, so the non-member operator is chosen.



回答2:

This behaviour makes complete sense:

  • When a member function exists and matches, then it is a good idea to use it in preference to a free function, otherwise code outside the class could inadvertently break up the class encapsulation (for example, if another member function were to use the operator<<).

  • Automatic conversion works by creating a list of candidate functions, then attempting to find conversions for any parameters that require it. In order to find the member function, a conversion would have to happen before building the candidate list, so only the free function is found.