Sobrecarga de operadores de comparación
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 42 de 104.
Los operadores de comparación como ==, !=, <, >, <= y >= te permiten comparar objetos de tus clases personalizadas. Estos operadores devuelven un bool y deben marcarse como const, ya que no modifican ninguno de los dos operandos.
class Date {
int year, month, day;
public:
Date(int y, int m, int d) : year(y), month(m), day(d) {}
bool operator==(const Date& other) const {
return year == other.year &&
month == other.month &&
day == other.day;
}
bool operator<(const Date& other) const {
if (year != other.year) return year < other.year;
if (month != other.month) return month < other.month;
return day < other.day;
}
};Una técnica útil es Implementar otros operadores de comparación en términos de los que ya has definido. Una vez que tienes == y <, el resto se deduce naturalmente:
bool operator!=(const Date& other) const {
return !(*this == other);
}
bool operator>(const Date& other) const {
return other < *this;
}
bool operator<=(const Date& other) const {
return !(other < *this);
}
bool operator>=(const Date& other) const {
return !(*this < other);
}Este enfoque reduce la duplicación de código y garantiza que todos tus operadores de comparison se comporten de forma coherente. Si más adelante cambias cómo funcionan la igualdad o menor que, los demás operadores se mantienen automáticamente sincronizados.
Desafío
FácilConstruyamos una clase Version que represente números de versión de software (como 2.1.0 o 3.0.5) y admita los seis operadores de comparación. Este es un caso práctico en el que comparar versiones determina qué software es más reciente: perfecto para practicar la sobrecarga de operadores de comparación.
Crearás dos archivos para organizar tu código:
Version.h: Define una claseVersionque almacene tres enteros que representen los números de versión major, minor y patch. Tu clase debe admitir:- Un constructor que acepte valores major, minor y patch
- Getters para cada componente:
getMajor(),getMinor(),getPatch()(todos const) - Los seis operadores de comparación:
==,!=,<,>,<=,>= - Un método
toString()que devuelva la versión como una cadena con el formato"major.minor.patch"
Implementa
==y<directamente; después, define los cuatro operadores restantes en términos de estos dos. Para la comparación menor que, compara primero major; después minor si los valores major son iguales; y luego patch si tanto major como minor son iguales. Todos los operadores de comparación deben ser funciones miembro const.main.cpp: Lee seis enteros de la entrada que representen dos versiones (major1, minor1, patch1, major2, minor2, patch2 en líneas separadas). Crea dos objetosVersiony compáralos usando todos tus operadores.Formato de salida:
Version 1: <v1> Version 2: <v2> v1 == v2: <true/false> v1 != v2: <true/false> v1 < v2: <true/false> v1 > v2: <true/false> v1 <= v2: <true/false> v1 >= v2: <true/false>Imprime
trueofalse(en lowercase) para cada resultado de comparación.
La técnica clave aquí consiste en implementar los cuatro operadores derivados (!=, >, <=, >=) usando únicamente == y <. Esto reduce la duplicación de código y garantiza que todos los operadores sigan siendo coherentes si alguna vez cambias la lógica de comparación.
Convierte las cadenas de entrada en enteros usando std::stoi(). Usa std::to_string() para construir la cadena de versión. No olvides las protecciones contra inclusiones múltiples en tu archivo de cabecera.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "Version.h"
using namespace std;
int main() {
// Leer seis enteros para dos versiones
string line;
getline(cin, line);
int major1 = stoi(line);
getline(cin, line);
int minor1 = stoi(line);
getline(cin, line);
int patch1 = stoi(line);
getline(cin, line);
int major2 = stoi(line);
getline(cin, line);
int minor2 = stoi(line);
getline(cin, line);
int patch2 = stoi(line);
// TODO: Crear dos objetos Version
// TODO: Mostrar Version 1 y Version 2 usando toString()
// TODO: Comparar usando los seis operadores y mostrar los resultados
// Usar "true" o "false" (minúsculas) para cada comparación
// Formato: "v1 == v2: true" o "v1 == v2: false"
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éricoPractica por tu cuenta: Compilador de C++ online