Cargando...

Sobrecarga de operadores en C++

Aprende la sobrecarga de operadores en C++ para personalizar operadores aritméticos y de comparación en tus clases.

En C++, la sobrecarga de operadores (operator overloading) permite redefinir los operadores estándar (+, ==, <, <<, etc.) para tipos de clase personalizados. Gracias a esta característica, los objetos de clase pueden comportarse como los tipos integrados (int, double, etc.). En este artículo, exploraremos los operadores aritméticos, de comparación y de flujo (stream) usando la clase Book como ejemplo.


1. ¿Qué es la sobrecarga de operadores?

La sobrecarga de operadores permite definir un comportamiento especial para los operadores en clases personalizadas. Por ejemplo, dos objetos Book pueden sumarse con + o compararse con ==.

Las funciones de operador se definen como funciones miembro normales:


class NombreClase {
public:
    TipoRetorno operator<Operador>(Parámetros) {
        // comportamiento personalizado
    }
};

Por ejemplo, Book operator+(const Book& other) indica que el operador + está definido para combinar dos objetos Book.


2. Clase base Book

La siguiente clase representa un libro con título, precio y número de páginas. Usaremos esta clase para implementar diferentes operadores.


#include <iostream>
#include <string>
using namespace std;

class Book {
private:
    string title;
    double price;
    int pages;

public:
    Book(string t = "", double p = 0.0, int pg = 0)
        : title(t), price(p), pages(pg) {}

    void Show() const {
        cout << "Libro: " << title
             << " | Páginas: " << pages
             << " | Precio: " << price << " €" << endl;
    }

    double GetPrice() const { return price; }
    int GetPages() const { return pages; }
    string GetTitle() const { return title; }
};

3. Operador + (Combinar dos libros)

Si sumamos dos libros con +, crearemos un nuevo libro “paquete”. El precio será la suma de los precios y el número de páginas la suma de ambas.


Book operator+(const Book &other) const {
    string combinedTitle = title + " & " + other.title;
    double combinedPrice = price + other.price;
    int combinedPages = pages + other.pages;
    return Book(combinedTitle, combinedPrice, combinedPages);
}

Uso:


Book b1("C++ Primer", 180.0, 980);
Book b2("Effective C++", 150.0, 400);

Book combo = b1 + b2;
combo.Show();

Salida:


Libro: C++ Primer & Effective C++
| Páginas: 1380 | Precio: 330 €

4. Operador == (Comparación de igualdad)

Para comprobar si dos libros son iguales, podemos sobrecargar el operador ==. Si el título, el precio y las páginas coinciden, se consideran iguales.


bool operator==(const Book &other) const {
    return (title == other.title &&
            pages == other.pages &&
            price == other.price);
}

Uso:


Book a("1984", 99.9, 328);
Book b("1984", 99.9, 328);

if (a == b)
    cout << "Los libros son iguales." << endl;
else
    cout << "Los libros son diferentes." << endl;

Salida:


Los libros son iguales.

5. Operador < (Comparación)

Para comparar libros según su precio, podemos sobrecargar el operador <. Este operador es útil, por ejemplo, en std::sort() o std::set.


bool operator<(const Book &other) const {
    return price < other.price;
}

Uso:


Book b1("C++ Primer", 180, 900);
Book b2("Clean Code", 220, 500);

if (b1 < b2)
    cout << b1.GetTitle() << " es más barato." << endl;

Salida:


C++ Primer es más barato.

6. Operador ++ (Incrementar páginas)

El operador ++ puede definirse en dos formas: prefijo y postfijo. En este ejemplo, incrementa el número de páginas del libro.


// Prefijo (++libro)
Book& operator++() {
    ++pages;
    return *this;
}

// Postfijo (libro++)
Book operator++(int) {
    Book temp = *this;
    pages++;
    return temp;
}

Uso:


Book b("C++ 101", 120.0, 250);
++b;  // prefijo
b++;  // postfijo
b.Show(); // 252 páginas

7. Operador << (Salida con ostream)

Para imprimir un objeto directamente con cout << b;, debemos sobrecargar globalmente el operador <<. Este operador normalmente devuelve una referencia a ostream.


friend ostream& operator<<(ostream &os, const Book &b) {
    os << "[Libro: " << b.title
       << ", Páginas: " << b.pages
       << ", Precio: " << b.price << " €]";
    return os;
}

Uso:


Book b("Clean Architecture", 175.0, 350);
cout << b << endl;

Salida:


[Libro: Clean Architecture, Páginas: 350, Precio: 175 €]

8. Ejemplo completo: todos los operadores juntos


#include <iostream>
#include <string>
using namespace std;

class Book {
private:
    string title;
    double price;
    int pages;

public:
    Book(string t = "", double p = 0, int pg = 0)
        : title(t), price(p), pages(pg) {}

    Book operator+(const Book &other) const {
        return Book(title + " & " + other.title,
                    price + other.price,
                    pages + other.pages);
    }

    bool operator==(const Book &other) const {
        return (title == other.title && price == other.price);
    }

    bool operator<(const Book &other) const {
        return price < other.price;
    }

    Book& operator++() {
        ++pages;
        return *this;
    }

    Book operator++(int) {
        Book temp = *this;
        pages++;
        return temp;
    }

    friend ostream& operator<<(ostream &os, const Book &b) {
        os << b.title << " - " << b.price << " € (" << b.pages << " páginas)";
        return os;
    }
};

int main() {
    Book b1("C++ Primer", 180.0, 900);
    Book b2("Effective C++", 150.0, 400);

    Book combo = b1 + b2;
    cout << combo << endl;

    ++combo;
    combo++;

    cout << "Después del incremento: " << combo << endl;

    cout << (b1 < b2 ? "b1 es más barato" : "b2 es más barato") << endl;

    if (b1 == b2)
        cout << "Los libros son iguales." << endl;
    else
        cout << "Los libros son diferentes." << endl;
}

Salida:


C++ Primer & Effective C++ - 330 € (1300 páginas)
Después del incremento: C++ Primer & Effective C++ - 330 € (1302 páginas)
b1 es más barato
Los libros son diferentes.

9. TL;DR

  • operator+ → para combinar dos objetos.
  • operator== → para verificar igualdad.
  • operator< → para comparar o ordenar.
  • operator++ → para incrementar (prefijo/postfijo).
  • operator<< → para imprimir con cout (requiere friend).
  • La sobrecarga de operadores hace que las clases se comporten como tipos integrados.
  • Todos los ejemplos pueden ejecutarse en Visual Studio 2022 o GCC 11+.

Artículos relacionados