¿Por qué debería sobrecargar un operador C ++ como función global (lo hace STL) y cuáles son las advertencias?

Why would I want to overload a C++ operator() as global and not member function. For example, the == operador.

Why is this done? for example in STL libraries.

preguntado el 28 de septiembre de 11 a las 05:09

I generally let questions percolate a few hours at least before choosing an answer. You never know who's going to come along with an answer that blows all the previous answers out of the water. -

That might very well be. But the answer you accepted doesn't really answer the question and goes on about somewhat irrelevant things. In my opinion, the best answer here is James Kranze's, which illustrates my point about waiting to accept very nicely. -

3 Respuestas

The usual rule is for operators which modify the left hand object to be members, and binary operators which return a new object to be free functions; the main motivation for the latter is because the compiler will not convert the left hand side to match a member; if your class supports cualquier implicit conversions, then all of the usual binary operators should be free functions, so that the same rules of conversion apply
for the left hand side and the right hand side, e.g.:

class Complex
{
public:
    Complex(double r, double i = 0.0);
    bool operator==( Complex const& other ) const;
};

Complex a;
//  ...
if ( a == 1.0 ) // OK
//  ...
if ( 1.0 == a ) // error.

pero:

class Complex
{
public:
    Complex(double r, double i = 0.0);
    friend bool operator==( Complex const& lhs, Complex const& rhs ) const;
};

Complex a;
//  ...
if ( a == 1.0 ) // OK
//  ...
if ( 1.0 == a ) // OK

One elegant way of achieving this is to define the basic operations in terms of member functions—for things like + or -, these would be operator+= y operator-=; for comparison, you'd need to define an arbitrary conventions, a member isEqualy compare (which would return <, == or > zero according to the results, then inherit from a template along the lines of:

template <typename T>
class ArithmeticOperators
{
    friend T operator+( T const& lhs, T const& rhs )
    {
        T result( lhs );
        result += rhs;
        return result;
    }
    //  And so on, for all of the binary operators.
};

class Complex : public ArithmeticOperators<Complex>
{
public:
    //  ...
    Complex& operator+=( Complex const& other );
    //  etc.
};

Note that there is some argument for making the operator <op>= functions free functions as well: the fact that the free function will take a non-const reference as its first argument, and thus requires an lvalue (like the built-in operator <op>=). This doesn't seem to be the usual practice, however, probably because operator= must be a member, and it seems more natural to treat the operator <op>= in the same mannter.

Respondido el 28 de Septiembre de 11 a las 12:09

Si recuerdo correctamente, operator = must be a member function. Regarding operator ==, I figure you don't actually mean global but free function instead (STL does not define operators globally). There are a couple of things to consider, one is decoupling from the class itself: If your operator can be defined in terms of the public interface of your class, then you are better off implementing it that way to keep the access to the implementation internals to the bare minimum. The other fundamental advantage is the possibility to implemement an operator where your type comes as the second operand, consider equality between types T and U:

bool operator ==( T const& t, U const& u ){ ... }
bool operator ==( U const& t, T const& u ){ ... }

If objects of type T and U can be equally compared, then it makes sense that both t == u y u == t are valid and both yield the same result. If you were defining this operator as a member function, then one would be within the implementation of T and the other within the implementation of U. Now consider U is a 3rd party type outside your control, or even better is a fundamental type such as int, now there is no other way for you to provide such operator but to provide the free function version of it.

Respondido el 28 de Septiembre de 11 a las 09:09

@unixman83: This is valid for any types T and U, be it int, my_class, std::string or whatever you can think of. - K-Ballo

The rules for matching a member function against an argument are different from the rules for matching the first argument of a free function. I'm not certain exactly how they are different, but since they are different it's actually preferable to implement most binary operators as free functions instead of member functions in order that argument matching operates symmetrically for both arguments.

There is an except for postfix ++, but that's because it isn't really a binary operator, and only plays one when you overload it in order to have a way of distinguishing between it and prefix ++.

Respondido el 28 de Septiembre de 11 a las 09:09

by Simétricamente he means that they will both call into the same code (usually the same function) instead of calling into whichever class is on the left-side of the =operator. - unixman83

The main difference is that in the case of a member function, the compiler is not allowed to apply implicit conversions on the left-hand-side of the operator: 5+x dónde x is of a type T implicitly convertible from int nunca llamaré T::operator+(T const &), but it can call operator+(T,T const&) breaking symmetry between the expressions 5+x y x+5. Additionally, pass-by-value optimization in the free signature cannot be applied in the case of a member function, that will require an extra copy. (más, ) - David Rodríguez - dribeas

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.