You're talking about
operator overloading, not just "overloading" (the latter is a generalization of the former).
Quote:
Anyways, I'm just wondering HOW I should code it.
Implement operator overloads that make sense for their context and do not alter the underlying semantics of the operator. Preserve expected behaviors (such as that of prefix or postfix increment). Read
this.
Quote:
I mean ones that EXPLAIN why you phrase it this way:
void operator<<(int& a);
And not this way:
friend Stream& operator(Stream& stream, int& a);
I've got to be honest, I know what friend are, but the whole overloading scheme doesn't make much sense...
friend is not strictly related here. Both forms of the overload are valid (assuming the first is a member function). For those operators that can be defined as members or non-members (some have restrictions), the choice between member and non-member is usually based on your judgement. There are situations where it is beneficial to do one or the other, however. For example, overloading operator* between a (geometric) vector and a float requires two overloads: one for operator*(float,vector) and one for operator*(vector,float) since either form is valid. In this case, the programmer will usually elect to implement the operators as non-members since you cannot provide the first form as a member, and one would generally prefer to the two forms of the operator to appear near eachother in the header.
Quote:
Yuck! Could I do it this way?
I don't see what is so "yucky" about the non-member version here, or how your member version is any prettier. It removes one (explicit) parameter.
Also note that the "friend" declaration is not required, and that your member version violates the "expected behavior" tenet, above (it does not return the Logger by reference and thus you cannot chain the operator).