Sobrecarga de Operadores de Comparação
Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 42 de 104.
Operadores de comparação como ==, !=, <code><, , <= e >= permitem comparar objetos de suas classes personalizadas. Esses operadores retornam um bool e devem ser marcados como const, já que não modificam nenhum 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;
}
};Uma técnica útil é implementar outros operadores de comparação em termos daqueles que você já definiu. Uma vez que você tenha == e <code><, o restante segue 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);
}Esta abordagem reduz a duplicação de código e garante que todos os seus operadores de comparação se comportem de forma consistente. Se você alterar posteriormente como a igualdade ou o "menor que" funcionam, os outros operadores permanecerão automaticamente em sincronia.
Desafio
FácilVamos construir uma classe Version que representa números de versão de software (como 2.1.0 ou 3.0.5) e suporta todos os seis operadores de comparação. Este é um caso de uso prático onde comparar versões determina qual software é mais recente — perfeito para praticar a sobrecarga de operadores de comparação.
Você criará dois arquivos para organizar seu código:
Version.h: Defina uma classeVersionque armazena três inteiros representando os números de versão major, minor e patch. Sua classe deve suportar:- Um construtor que recebe os valores major, minor e patch
- Getters para cada componente:
getMajor(),getMinor(),getPatch()(todos const) - Todos os seis operadores de comparação:
==,!=,<,>,<=,>= - Um método
toString()que retorna a versão como uma string no formato"major.minor.patch"
Implemente
==e<diretamente, depois defina os quatro operadores restantes em termos destes dois. Para a comparação "menor que", compare primeiro o major, depois o minor se os majors forem iguais, e então o patch se tanto o major quanto o minor forem iguais. Todos os operadores de comparação devem ser funções membros const.main.cpp: Leia seis inteiros da entrada representando duas versões (major1, minor1, patch1, major2, minor2, patch2 em linhas separadas). Crie dois objetosVersione compare-os usando todos os seus operadores.Formato de saída:
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>Imprima
trueoufalse(minúsculo) para cada resultado de comparação.
A técnica principal aqui é implementar os quatro operadores derivados (!=, >, <=, >=) usando apenas == e <. Isso reduz a duplicação de código e garante que todos os operadores permaneçam consistentes se você alterar a lógica de comparação.
Converta as strings de entrada para inteiros usando std::stoi(). Use std::to_string() para construir a string da versão. Não se esqueça dos header guards em seu arquivo de cabeçalho.
Folha de consulta
Operadores de comparação (==, !=, <code><, , <=, >=) permitem comparar objetos de classes personalizadas. Esses operadores retornam um bool e devem ser marcados como const, pois não modificam nenhum 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;
}
};Implemente outros operadores de comparação em termos de == e <code>< para reduzir a duplicação de código e garantir a consistência:
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);
}Experimente você mesmo
#include <iostream>
#include <string>
#include "Version.h"
using namespace std;
int main() {
// Lê seis inteiros para duas versões
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: Criar dois objetos Version
// TODO: Exibir Version 1 e Version 2 usando toString()
// TODO: Comparar usando todos os seis operadores e exibir os resultados
// Use "true" ou "false" (minúsculo) para cada comparação
// Formato: "v1 == v2: true" ou "v1 == v2: false"
return 0;
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP
Arquivos ExternosBuild e Compilação em C++Arquivos Header e SourceNamespaces e EscopoIntrodução a OOP em C++Classes vs ObjetosO Ponteiro 'this'Métodos (Funções Membro)Atributos (Membros de Dados)Básico de Ctors e DtorsRecapitulação - Calculadora Simples4Propriedades de Classe
Membros de Instância vs EstáticosGetters e SettersFunções de Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRecapitulação - Gerenciador de Conta Bancária7Herança
Herança BásicaNíveis de Acesso na HerançaOrdem de Chamada de Ctor e DtorSobrescrita de MétodosFunções Virtuais e VTableHerança MúltiplaHerança VirtualRecapitulação - Hierarquia de Funcionários2Gerenciamento de Memória
Memória Stack vs HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Smart Pointers em C++RAII em C++Recapitulação - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de Acesso em C++Especificadores de Acesso em DetalhesOcultação de InformaçãoStruct vs ClassClasses Aninhadas e InternasRecapitulação - Sistema de Registros de Alunos8Polimorfismo
Polimorfismo de Compilação vs Tempo de ExecuçãoSobrecarga de FunçõesFunções Virtuais RevisitadasFunções Virtuais PurasClasses AbstratasDesign de Interfaces em C++Dynamic Casting e RTTIRecapitulação - Calculadora de Formas3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentaçãoListas de Inicialização do ConstrutorConstrutores DelegadosMergulho Profundo em DestrutoresRegra dos Três / Cinco / ZeroRecapitulação - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de StreamSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçãoTemplates de ClasseEspecialização de TemplatesTemplates VariádicosFundamentos de SFINAE e Type TraitsRecapitulação - Container Genérico