Menu
Coddy logo textTech

Clases abstractas

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

Una clase abstracta es cualquier clase que contiene al menos una función virtual pura. Debido a que tiene una interfaz incompleta, no puedes crear objetos de una clase abstracta directamente: existe únicamente para que se herede de ella.

class Shape {
public:
    virtual double area() = 0;      // Virtual pura - hace que Shape sea abstracta
    virtual double perimeter() = 0; // Otra función virtual pura
    
    void printInfo() {              // Método regular - tiene implementación
        std::cout << "Area: " << area() << std::endl;
    }
    
    virtual ~Shape() = default;
};

Shape s;  // Error: no se puede instanciar una clase abstracta

Las clases abstractas pueden contener una combinación de funciones virtuales puras (sin implementación), funciones virtuales normales (con implementación predeterminada) y funciones no virtuales. Esto te permite definir un comportamiento común y, al mismo tiempo, exigir que las clases derivadas implementen una funcionalidad específica.

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() override { return 3.14159 * radius * radius; }
    double perimeter() override { return 2 * 3.14159 * radius; }
};

Circle c(5.0);      // OK: Circle implementa todas las funciones virtuales puras
c.printInfo();      // Usa el printInfo() heredado, llama a area() de Circle

Una clase derivada debe implementar todas las funciones virtuales puras para volverse concreta (instanciable). Si deja alguna sin implementar, sigue siendo abstracta. Este mecanismo garantiza que cada clase concreta de tu jerarquía proporcione la funcionalidad requerida.

challenge icon

Desafío

Fácil

Construyamos un sistema de reproductor multimedia que demuestre cómo las clases abstractas definen contratos para distintos tipos de medios. Crearás una clase base abstracta que establece lo que todo reproductor multimedia debe hacer y, después, implementarás reproductores concretos para contenido de audio y vídeo.

Organizarás tu código en tres archivos:

  • MediaPlayer.h: Define una clase abstracta MediaPlayer que sirve como modelo para todos los tipos de medios. Tu clase abstracta debe tener:
    • Un miembro protegido std::string title
    • Un miembro protegido int duration (en segundos)
    • Un constructor que inicialice ambos valores
    • Un método virtual puro play(): cada tipo de medio se reproducirá de manera diferente
    • Un método virtual puro getMediaType() que devuelva un std::string
    • Un método regular (no virtual) showInfo() que imprima: <title> (<duration>s) - Type: <mediaType>. Este método debe llamar a getMediaType() para obtener el tipo
    • Un destructor virtual
  • Players.h: Implementa dos reproductores multimedia concretos que hereden de MediaPlayer:

    AudioPlayer:

    • Un miembro privado std::string artist
    • Un constructor que reciba el título, la duración y el artista
    • Implementa play() para imprimir: Playing audio: <title> by <artist>
    • Implementa getMediaType() para devolver "Audio"

    VideoPlayer:

    • Un miembro privado std::string resolution
    • Un constructor que reciba el título, la duración y la resolución
    • Implementa play() para imprimir: Playing video: <title> in <resolution>
    • Implementa getMediaType() para devolver "Video"
  • main.cpp: Lee cuatro entradas (cada una en una línea separada):
    1. Título de la pista de audio
    2. Duración del audio (entero)
    3. Título del vídeo
    4. Duración del vídeo (entero)

    Crea un AudioPlayer con el artista "Unknown Artist" y un VideoPlayer con la resolución "1080p". Almacena ambos en un arreglo de punteros MediaPlayer*.

    Recorre el arreglo y, para cada reproductor, llama primero a showInfo() y después a play(). Imprime una línea en blanco entre cada elemento multimedia. Libera los objetos asignados dinámicamente cuando hayas terminado.

Por ejemplo, con las entradas Summer Vibes, 180, Nature Documentary y 3600:

Summer Vibes (180s) - Type: Audio
Playing audio: Summer Vibes by Unknown Artist

Nature Documentary (3600s) - Type: Video
Playing video: Nature Documentary in 1080p

Observa cómo el método showInfo() se define una sola vez en la clase base abstracta, pero llama al método virtual puro getMediaType(). Esto demuestra cómo las clases abstractas pueden combinar implementaciones concretas con métodos que las clases derivadas deben proporcionar. Recuerda usar la palabra clave override en todos los métodos sobrescritos.

Pruébalo tú mismo

#include <iostream>
#include <string>
#include "MediaPlayer.h"
#include "Players.h"

int main() {
    // Leer entradas
    std::string audioTitle;
    int audioDuration;
    std::string videoTitle;
    int videoDuration;
    
    std::getline(std::cin, audioTitle);
    std::cin >> audioDuration;
    std::cin.ignore();
    std::getline(std::cin, videoTitle);
    std::cin >> videoDuration;
    
    // TODO: Crea un AudioPlayer con el artista "Unknown Artist"
    
    // TODO: Crea un VideoPlayer con resolución "1080p"
    
    // TODO: Almacena ambos en un array de punteros MediaPlayer*
    
    // TODO: Recorre el array y para cada player:
    //       1. Llama a showInfo()
    //       2. Llama a play()
    //       3. Imprime una línea en blanco entre cada elemento multimedia
    
    // TODO: Limpia los objetos asignados dinámicamente
    
    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