Introducción a la sobrecarga de operadores
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 40 de 104.
La sobrecarga de operadores te permite definir cómo se comportan los operadores como +, - o == cuando se usan con tus clases personalizadas. En lugar de llamar a métodos como a.add(b), puedes escribir el más intuitivo a + b.
En C++, los operadores son esencialmente funciones con nombres especiales. Para sobrecargar un operador, se define una función utilizando la palabra clave operator seguida del símbolo:
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// Sobrecargar el operador +
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};Ahora puedes sumar dos vectores de forma natural:
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // Llama a v1.operator+(v2)No todos los operadores pueden ser sobrecargados. El operador de resolución de ámbito ::, el acceso a miembros ., el ternario ?: y sizeof no pueden ser sobrecargados. Además, no se pueden crear nuevos operadores ni cambiar la precedencia de un operador: * siempre se evaluará antes que +.
Los operadores pueden implementarse como funciones miembro (como arriba) o como funciones no miembro. En las próximas lecciones, aprenderás cuándo usar cada enfoque y cómo sobrecargar categorías específicas de operadores.
Desafío
FácilVamos a construir una clase Point que represente una coordenada 2D y admita la suma de dos puntos utilizando el operador +. Este es tu primer paso en la sobrecarga de operadores: hacer que tus clases personalizadas funcionen con operadores familiares.
Crearás dos archivos para organizar tu código:
Point.h: Define una clasePointque almacene coordenadas x e y (ambasint). Tu clase debe tener:- Miembros privados para las coordenadas x e y
- Un constructor que reciba los valores x e y
- Getters
getX()ygetY()(ambos const) - Un operador
+sobrecargado que sume dos puntos y devuelva un nuevoPointcon las coordenadas combinadas
El operador
+debe implementarse como una función miembro que reciba otroPointpor referencia constante y devuelva un nuevoPoint. Márcalo comoconstya que no modifica ninguno de los operandos.main.cpp: Lee cuatro enteros de la entrada (x1, y1, x2, y2 en líneas separadas) que representan dos puntos. Crea dos objetosPoint, súmalos usando el operador+y muestra los resultados.Formato de salida:
Point 1: (<x1>, <y1>) Point 2: (<x2>, <y2>) Sum: (<sum_x>, <sum_y>)
La idea clave aquí es que p1 + p2 en realidad está llamando a p1.operator+(p2) entre bastidores. Tu operador sobrecargado te permite escribir código intuitivo como Point p3 = p1 + p2; en lugar de algo como Point p3 = p1.add(p2);.
Convierte las cadenas de entrada a enteros usando std::stoi(). No olvides los protectores de inclusión (header guards) en tu archivo de cabecera.
Hoja de referencia
La sobrecarga de operadores permite definir cómo se comportan los operadores como +, - o == con clases personalizadas, permitiendo una sintaxis intuitiva como a + b en lugar de a.add(b).
Para sobrecargar un operador, defina una función utilizando la palabra clave operator seguida del símbolo:
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// Sobrecargar el operador +
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};Uso:
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // Llama a v1.operator+(v2)Algunos operadores no se pueden sobrecargar: ::, ., ?: y sizeof. No se pueden crear nuevos operadores ni cambiar la precedencia de los operadores.
Los operadores pueden implementarse como funciones miembro o funciones no miembro.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "Point.h"
using namespace std;
int main() {
// Leer la entrada
string line1, line2, line3, line4;
getline(cin, line1);
getline(cin, line2);
getline(cin, line3);
getline(cin, line4);
int x1 = stoi(line1);
int y1 = stoi(line2);
int x2 = stoi(line3);
int y2 = stoi(line4);
// TODO: Crear dos objetos Point usando los valores de entrada
// TODO: Sumar los dos puntos usando el operador +
// TODO: Mostrar los resultados en el formato requerido:
// Point 1: (<x1>, <y1>)
// Point 2: (<x2>, <y2>)
// Suma: (<sum_x>, <sum_y>)
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