Operator Overloading (C++)

Operator Functions
The name of an operator function is the keyword operator followed by the operator itself; for example, operator<<. An operator function is declared and can be called like any other function. A use of the operator is only a shorthand for an explicit call of the operator function. For example:

Binary and Unary Operators
A binary operator can be defined by either a nonstatic member function taking one argument or a nonmenber function taking two arguments. For any binary operator @, aa@bb can be interpreted as either aa.operator@(bb) or operator@(aa, bb). If both are defined, overload resolution determines which, if any, interpretation is used. For example:

A unary operator, whether prefix or postfix, can be defined by either a nonstatic member function taking no arguments or a nonmenber function taking one argument. For any prefix unary operator @, @aa can be interpreted as either aa.operator@ or operator@(aa). If both are defined, overload resolution determines which, if any, interpretation is used. For any postfix unary operator @, aa@ can be interpreted as either aa.operator@(int) or operator@(aa, int). If both are defined, overload resolution determines which, if any, interpretation is used. Examples:

Operators and User-Defined Types
An operator function must either be a member or take at least one argument of a user-defined type. An operator function intended to accept a basic type as its first operand cannot be a member function. For example, consider adding a complex variable aa to the integer 2: aa + 2 can, with a suitably declared member function, be interpreted as aa.operator+(2), but 2 + aa cannot because there is no class int for which to define + to mean 2.operator+(aa). This example is trivially handled using nonmember functions.

Enumerations are user-defined types so that we can define operators for them. For example:

Binary Stream Insertion and Extraction Operators
The C++ class libraries overload these binary operators for each fundamental type, including pointers and char* strings. You can also overload these operators to perform input and output for your own types.

Unary Prefix and Postfix ++ and -- Operators
The prefix increment operator implemented as a member function:

The prefix increment operator implemented as a non-member function:

Overloading the posfix increment operator presents a challenge, because the compiler must be able to distinguish between the signatures of the overloaded prefix and posfix increment operator functions. The convention that has been adopted is that, when the compiler sees the postincrementing expression d1++, it generates the member-function call

The argument 0 is strictly a "dummy value" that enables the compiler to distinguish between the prefix and postfix increment operator functions. The same syntax is used to differentiate between the prefix and postfix decrement operator functions.

If the postfix increment is implemented as a non-member function, then the compiler generates the function call:

Note that the postfix increment operator returns Date objects by value, whereas the prefix increment operator returns Date objects by reference. The postfix increment operator typically returns a temporary object that contains the original value of the object that contains the original value of the object before the increment occurred. C++ treats such objects as //rvalues//, which cannot be used on the left side of an assignment. The prefix increment operator returns the actual incremented object with its new value. Such an object can be used as an //lvalue// in a continuing expression.

The extra object that's created by the postfix increment (or decrement) operator can result in a performance problem - especially when the operator is used in a loop. For this reason, you should prefer the overloaded prefix increment and decrement operators.

Objekt som returverdi
Vi bruker et objekt som returverdi når operatoren har som oppgave å lage et nytt objekt av samme type som *this. De mest aktuelle operatorene av denne typen er de binære operatorene + - * / % og de unære operatorene + og -.

*this som returverdi
Når vi vil at *this skal forandres, bruker vi normalt en referanse til *this som funksjonsverdi. Operatoren = er et eksempel på dette. Her vil vi at første operand (det som står foran likhetstegnet) skal få samme verdi som andre operand (det som står bak). Vi lager følgende implementasjon:

Merk: Kompilatoren definerer en standardversjon av operatoren = hvis vi ikke lager en egen utgave av denne operatoren. Standardversjonen sier at et objekt settes lik et annet objekt ved å sette alle datamedlemmene i det ene objektet lik de tilsvarende datamedlemmene i det andre. Dette fungerer ikke tilfredsstillende dersom vi har en peker som datamedlem.

De mest vanlige operatorene som bør returnere **//*this//** er ++ -- og alle tilordningsoperatorene (= += -= osv.).

Diverse returverdier
Noen operatorer gir en annen returverdi enn et objekt eller en referanse til et objekt. Sammenlikningsoperatorene er et godt eksempel på dette. Vi lar dem ha typen bool.

Å definere operatorer som ikke-medlemsfunksjoner
Det er også mulig å lage operator-funksjoner som ikke-medlemsfunksjoner. Det fins to grunner til det:
 * 1) Første operand skal ikke være et objekt av den klassen vi skal knytte operatoren til.
 * 2) Vi ønsker å definere en operator knyttet til en klasse som vi ikke har herredømme over.

Se over...