Sobrecarga de Operadores: material adaptado de The cplusplus.com tutorial

C++ permite usar operadores estándares como +,-, y * con operandos objetos. De este modo podemos hacer operaciones con instancias de una clase igual como con los tipos fundamentales. Por ejemplo:

int a, b, c;
a = b + c;
es perfectamente válido, dado que las variables son todas tipos fundamentales. Sin embargo, en C no podemos efectuar la operación siguiente (de hecho es incorrecto):
struct { char product [50]; float price; } a, b, c;
a = b + c;
Lo que conduce a error es el uso del operador adición, que en principio no es válido entre tipos no fundamentales.

Pero en C++, podemos hacer que objetos, instancias de tipos compuestos, como los previos pueden aceptar operadores que de otra manera no serían aceptados. Incluso es posible redefinir el efecto de operadores ya permitidos. La lista de operadores que puede ser sobrecargados es:

+    -    *    /    =    <    >    +=   -=   *=   /=   <<   >>
<<= >>= == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [] () new delete
Para sobrecargar un operador, sólo necesitamos escribir una función miembro en la clase cuyo nombre es  operator seguido por el signo del operador que queremos sobrecargar, siguiendo este prototipo:
type operator sign (parameters);
Aquí tenemos un ejemplo que incluye el operador  +. Vamos a sumar vectores bidimensionales a(3,1) y b(1,2). En este caso el resultado será (3+1,1+2) = (4,3).

// vectors: overloading operators example
#include <iostream.h>

class CVector {
  public:
    int x,y;
    CVector () {};
    CVector (int,int);
    CVector operator + (CVector);
};

CVector::CVector (int a, int b) {
  x = a;
  y = b;
}

CVector CVector::operator+ (CVector param) {
  CVector temp;
  temp.x = x + param.x;
  temp.y = y + param.y;
  return (temp);
}

int main () {
  CVector a (3,1);
  CVector b (1,2);
  CVector c;
  c = a + b;
  cout << c.x << "," << c.y;
  return 0;
}
      
4,3

No se confunda por el hecho de ver muchos  CVector. Uno es el nombre de la clase CVector, otros son nombres de métodos (constructor y destructor - no en este caso ), y otros son valores retornados en métodos. 

CVector (int, int);            // function name CVector (constructor)
CVector operator+ (CVector);   // function operator+ that returns CVector type
  
La función operator+ de la clase CVector es la encargada de sobrecargar el operador aritmético  +. Hay dos formas para llamar esta operación:
c = a + b;   // notar el orden usado para operadores infijos
c = a.operator+(b);  // esta es la forma en que el compilador implementa la línea previa.

Igual como una clase incluye por omisión un constructor de copia y constructor vacío (sin argumentos), ésta también incluye un definición por omisión para el operador de asignación (=) entre dos instancias de la misma clase. Este método copia el contenido bit a bit de los miembros no estáticos del objeto de la derecha al de la izquierda. Por supuesto, podemos redefinir este operador con cualquier otra funcionalidad que se desee; por jemplo, copia en profundidad cuando se tienen miembros datos punteros.

La sobrecarga de operadores no nos obliga a seguir el mismo significado matemático o usual del operador, aún así es recomendado (por consistencia e interpretación intuitiva). Por ejemplo, no es lógico usar el operador + para restar dos objetos u operador  == para asignar ceros a un objeto, aún cuando esto sea posible.

El prototipo de la función operator+ puede resultar obvio, pero para otros operadores pueden no serlo. Aquí se tiene una tabla que resume cómo declarar las diferentes funciones de sobrecarga  (reemplace @ por el operador en cada claso):

Expression Comentario
Operator (@) Function member Global function
@a prefijo
+ - * & ! ~ ++ -- A::operator@() operator@(A)
a@ postfijo
++ -- A::operator@(int) operator@(A, int)
a@b infijo
+ - * / % ^ & | < > == != <= >= << >> && || , A::operator@(B) operator@(A, B)
a@b infijo
= += -= *= /= %= ^= &= |= <<= >>= [] A::operator@(B) -
a(b, c...) postfijo
() A::operator()(B, C...) -
a->b infijo
-> A::operator->(B) -
a es un objeto o instancia de clase Ab es una instancia de clase B y c es instancia de calse C. B y C podrían ser tipos básicos.
Se puede ver en esta tabla que algunos operadores se pueden sobrecargar de dos formas: como funciones miembro de la clase del operando del lado izquierdo (excepto caso @a) o como funciones globales. No hay diferencia en su uso; sin embargo, hay que recordar que funciones no miembros de la clase no pueden acceder a los miembros  private o protected. Por este caso y otras situaciones, C++ permite en una clase declarar como amigas a funciones globales, además de otras clases (friend, se verá más adelante).
Cabe destacar que en ocasiones no es posible sobrecargar el operador dentro de la clase, por ejemplo, cuando la clase ya está definida en el lenguaje. Éste es el caso de cout << objeto;
Para hacer esta operación, deberíamos definir el operador << en la clase ostream (de la cual cout es instancia). Nuestra mejor y única opción es definir la función global:
ostream operator <<(ostream, MiClase){
....
}