La sobrecarga de funciones (overloading) es un mecanismo que permite declarar múltiples funciones con el mismo nombre, pero con diferentes firmas (número o tipo de parámetros).
Los valores por defecto para los parámetros se pueden especificar en la declaración de las funciones. Sutileza: los valores por defecto solo se tienen en cuenta durante la compilación de la llamada y son sustituidos por el compilador, basándose en la firma visible.
En las clases, a menudo se encuentra la situación:
class Printer { void print(int n, char c = '*') { /* ... */ } void print(const std::string& s) { /* ... */ } }; Printer p; p.print(5); // llamará a print(int n, char c = '*'), c = '*' p.print("Hi"); // llamará a print(const std::string&)
Sutilezas:
void foo(int x, int y = 10); void foo(int x); foo(1); // Error: no está claro qué función llamar
¿Cuál es el único lugar donde se permite especificar un valor por defecto para una función miembro de la clase?
Respuesta: Se permite especificar un valor por defecto para un método de clase en la declaración del método dentro de la clase (o en la primera declaración fuera de la clase), pero no se permite especificarlo tanto en la clase como en la implementación. De lo contrario, se producirá un error de definición repetida.
class X { void func(int x = 5); // Se puede aquí }; void X::func(int x) { /* ... */ } // ¡Pero no aquí!
Historia 1
En el software bancario, ocurrió un error en la etapa de compilación: parte de las funciones sobrecargadas con diferentes valores por defecto obstaculizaron la elección clara de la necesaria, las llamadas eran ambiguas en la etapa de compilación — el resultado, imposibilidad de compilar la versión final hasta corregir manualmente.
Historia 2
En el equipo existía un estilo generalizado en el que todos los valores por defecto se movían a la implementación, y no a la cabecera de la clase, sin embargo, para algunos métodos de clase esto causaba descoordinación entre la interfaz y la implementación — diferentes unidades de traducción veían diferentes parámetros de función, lo que llevaba a extraños errores de compilación y en tiempo de ejecución.
Historia 3
Al ampliar una biblioteca pública, se añadió erróneamente una sobrecarga de función con los mismos parámetros, pero diferentes valores por defecto. El compilador comenzó a arrojar ambigüedad durante las llamadas a la API, y los usuarios se encontraron con llamadas obsoletas y problemas de compatibilidad binaria rota.