Menu
CoddyTech

Sobrescritura de métodos

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 51 de 104.

La sobrescritura de métodos ocurre cuando una clase derivada proporciona su propia implementación de un método que ya existe en la clase base. Esto permite que las clases derivadas personalicen el comportamiento heredado mientras conservan la misma firma del método.

Para sobrescribir un método, simplemente define un método en la clase derivada con exactamente el mismo nombre, tipo de retorno y parámetros:

class Animal {
public:
    void speak() {
        std::cout << "Some sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void speak() {
        std::cout << "Woof!" << std::endl;
    }
};

Dog d;
d.speak();  // Salida: Woof!

La versión de la clase derivada oculta la versión de la clase base. Sin embargo, todavía puedes acceder al método de la clase base usando el operador de resolución de ámbito:

class Dog : public Animal {
public:
    void speak() {
        Animal::speak();  // Llama a la versión de la clase base
        std::cout << "Woof!" << std::endl;
    }
};

Existe una limitación importante en esta forma básica de sobrescritura. Cuando accedes a un objeto derivado mediante un puntero o una referencia a la clase base, se llama a la versión de la clase base en su lugar:

Dog d;
Animal* ptr = &d;
ptr->speak();  // Salida: Algún sonido (no Woof!)

Esto ocurre porque el compilador determina qué método llamar según el tipo del puntero, no el tipo real del objeto. Para lograr un verdadero polimorfismo en tiempo de ejecución, en el que se llame al método correcto según el objeto real, necesitarás funciones virtuales, que veremos en la siguiente lección.

challenge icon

Desafío

Fácil

Vamos a crear un sistema de notificaciones que demuestra cómo funciona la sobrescritura de métodos. Crearás una clase base Notifier y dos notificadores especializados que personalizan la forma de entregar los mensajes.

Organizarás el código en tres archivos:

  • Notifier.h: Define una clase base Notifier con:
    • Un miembro protegido std::string recipient
    • Un constructor que recibe un nombre de destinatario y lo almacena
    • Un método público send(const std::string& message) que imprime: Sending to <recipient>: <message>
  • EmailNotifier.h: Define una clase EmailNotifier que hereda públicamente de Notifier:
    • Un constructor que recibe un destinatario y se lo pasa a la clase base
    • Sobrescribe el método send() para llamar primero a la versión de la clase base mediante Notifier::send() y después imprimir: [Email sent successfully]
  • main.cpp: Lee dos entradas (cada una en una línea distinta):
    1. Nombre del destinatario (cadena)
    2. Contenido del mensaje (cadena)

    Define una clase SMSNotifier directamente en main.cpp que hereda públicamente de Notifier:

    • Un constructor que recibe un destinatario y se lo pasa a la clase base
    • Sobrescribe el método send() para imprimir: SMS to <recipient>: <message> (reemplazando por completo el comportamiento de la clase base sin llamarlo)

    Crea un objeto de cada tipo de notificador (la clase base Notifier, EmailNotifier y SMSNotifier) usando el mismo destinatario. Llama a send() en cada uno con el mensaje de entrada e imprime una línea separadora entre cada llamada:

    --- Base Notifier ---
    <output>
    --- Email Notifier ---
    <output>
    --- SMS Notifier ---
    <output>

Por ejemplo, con las entradas Alice y Hello there!:

--- Base Notifier ---
Sending to Alice: Hello there!
--- Email Notifier ---
Sending to Alice: Hello there!
[Email sent successfully]
--- SMS Notifier ---
SMS to Alice: Hello there!

Observa cómo EmailNotifier amplía el comportamiento de la clase base al llamar primero al método de la clase padre, mientras que SMSNotifier lo reemplaza por completo con su propia implementación. No olvides las protecciones de encabezado e incluir los encabezados adecuados en cada archivo.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "Notifier.h"
#include "EmailNotifier.h"

using namespace std;

// TODO: Define aquí la clase SMSNotifier que hereda públicamente de Notifier
// - Constructor que pasa recipient a la clase base
// - Sobrescribe send() para imprimir: SMS to <recipient>: <message>
//   (reemplaza por completo el comportamiento de la clase base; no llames a send() de la clase padre)

int main() {
    string recipient;
    string message;
    
    getline(cin, recipient);
    getline(cin, message);
    
    // TODO: Crea un objeto Notifier con recipient
    // Imprime "--- Base Notifier ---"
    // Llama a send() con message
    
    // TODO: Crea un objeto EmailNotifier con recipient
    // Imprime "--- Email Notifier ---"
    // Llama a send() con message
    
    // TODO: Crea un objeto SMSNotifier con recipient
    // Imprime "--- SMS Notifier ---"
    // Llama a send() con message
    
    return 0;
}
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de C++ online