Sobrecarga de funciones
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 57 de 104.
La sobrecarga de funciones te permite definir múltiples funciones con el mismo nombre pero con diferentes listas de parámetros. El compilador selecciona la versión correcta basándose en los argumentos que pases. Esta es una forma clave de polimorfismo en tiempo de compilación.
Para que la sobrecarga funcione, las funciones deben diferir en su firma: el número de parámetros, sus tipos, o ambos:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
Calculator calc;
calc.add(5, 3); // Llama a add(int, int)
calc.add(2.5, 3.7); // Llama a add(double, double)
calc.add(1, 2, 3); // Llama a add(int, int, int)El compilador examina cada llamada y la asocia con la sobrecarga adecuada. Esto ocurre completamente en tiempo de compilación, por lo que no hay sobrecarga en tiempo de ejecución.
Importante: El tipo de retorno por sí solo no distingue las funciones sobrecargadas. Lo siguiente causaría un error de compilación:
int getValue();
double getValue(); // Error: no se puede sobrecargar solo por el tipo de retornoLa sobrecarga de funciones hace que su código sea más intuitivo. En lugar de crear nombres separados como addInts, addDoubles y addThreeInts, utiliza un único nombre significativo y deja que el compilador se encargue del resto.
Desafío
FácilVamos a construir una clase formateadora de mensajes que demuestre el poder de la sobrecarga de funciones. Crearás una clase Formatter con múltiples métodos format() que manejan diferentes tipos de entrada, permitiendo que el compilador elija la versión correcta basándose en lo que le pases.
Organizarás tu código en dos archivos:
Formatter.h: Define una claseFormattercon métodosformat()sobrecargados que manejen diferentes escenarios:- Un método que toma un solo
std::stringe imprime:Message: <text> - Un método que toma un
std::stringy un nivel de prioridadint, imprimiendo:[Priority <priority>] <text> - Un método que toma un
std::stringy una marca de tiempodouble, imprimiendo:[<timestamp>s] <text> - Un método que toma tres parámetros
std::string(sender, receiver, message) e imprime:From <sender> to <receiver>: <message>
format()— el compilador seleccionará el correcto basándose en los argumentos.- Un método que toma un solo
main.cpp: Lee cuatro entradas (cada una en una línea separada):- Un texto de mensaje simple
- Un nivel de prioridad (entero)
- Una marca de tiempo (double)
- Un nombre de remitente
Crea un objeto
Formattery demuestra los cuatro métodos sobrecargados:- Llama a
format()solo con el texto del mensaje - Llama a
format()con el texto del mensaje y la prioridad - Llama a
format()con el texto del mensaje y la marca de tiempo - Llama a
format()con el remitente, "Admin" como receptor, y el texto del mensaje
Por ejemplo, con las entradas System ready, 3, 12.5, y Server:
Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System readyObserva cómo llamas al mismo nombre de método format() cuatro veces, pero cada llamada invoca una versión diferente basada en los tipos y la cantidad de argumentos. Esto es polimorfismo en tiempo de compilación en acción: el compilador determina qué sobrecarga usar incluso antes de que el programa se ejecute.
Hoja de referencia
La sobrecarga de funciones permite definir múltiples funciones con el mismo nombre pero con diferentes listas de parámetros. El compilador selecciona la versión correcta basándose en los argumentos pasados en tiempo de compilación.
Las funciones deben diferir en su firma: el número de parámetros, sus tipos, o ambos:
class Calculator {
public:
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
};
Calculator calc;
calc.add(5, 3); // Llama a add(int, int)
calc.add(2.5, 3.7); // Llama a add(double, double)
calc.add(1, 2, 3); // Llama a add(int, int, int)Importante: El tipo de retorno por sí solo no puede distinguir funciones sobrecargadas:
int getValue();
double getValue(); // Error: no se puede sobrecargar solo por el tipo de retornoLa sobrecarga de funciones es una forma de polimorfismo en tiempo de compilación sin sobrecarga en tiempo de ejecución.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "Formatter.h"
using namespace std;
int main() {
// Leer las entradas
string message;
getline(cin, message);
int priority;
cin >> priority;
double timestamp;
cin >> timestamp;
cin.ignore();
string sender;
getline(cin, sender);
// TODO: Crear un objeto Formatter
// TODO: Llamar a format() solo con el texto del mensaje
// TODO: Llamar a format() con el texto del mensaje y priority
// TODO: Llamar a format() con el texto del mensaje y timestamp
// TODO: Llamar a format() con sender, "Admin" como receptor, y el texto del mensaje
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genérico