Menu
Coddy logo textTech

Classes abstratas

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy. Lição 60 de 104.

Uma classe abstrata é qualquer classe que contenha pelo menos uma função virtual pura. Como ela tem uma interface incompleta, você não pode criar objetos de uma classe abstrata diretamente — ela existe exclusivamente para ser herdada.

class Shape {
public:
    virtual double area() = 0;      // Virtual pura - torna Shape abstrata
    virtual double perimeter() = 0; // Outra função virtual pura
    
    void printInfo() {              // Método regular - tem implementação
        std::cout << "Area: " << area() << std::endl;
    }
    
    virtual ~Shape() = default;
};

Shape s;  // Erro: não é possível instanciar classe abstrata

Classes abstratas podem conter uma combinação de funções virtuais puras (sem implementação), funções virtuais regulares (com implementação padrão) e funções não virtuais. Isso permite definir um comportamento comum e, ao mesmo tempo, exigir que as classes derivadas implementem funcionalidades específicas.

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 as funções virtuais puras
c.printInfo();      // Usa o printInfo() herdado, chama o area() de Circle

Uma classe derivada deve implementar todas as funções virtuais puras para se tornar concreta (instanciável). Se deixar alguma sem implementação, ela própria permanecerá abstrata. Esse mecanismo garante que toda classe concreta na sua hierarquia forneça a funcionalidade necessária.

challenge icon

Desafio

Fácil

Vamos criar um sistema de reprodutor de mídia que demonstra como classes abstratas definem contratos para diferentes tipos de mídia. Você criará uma classe base abstrata que estabelece o que todo reprodutor de mídia deve fazer e, em seguida, implementará reprodutores concretos para conteúdo de áudio e vídeo.

Você organizará seu código em três arquivos:

  • MediaPlayer.h: Defina uma classe abstrata MediaPlayer que sirva como modelo para todos os tipos de mídia. Sua classe abstrata deve ter:
    • Um membro std::string title protegido
    • Um membro int duration protegido (em segundos)
    • Um construtor que inicialize ambos os valores
    • Um método virtual puro play(): cada tipo de mídia será reproduzido de maneira diferente
    • Um método virtual puro getMediaType() que retorne uma std::string
    • Um método comum (não virtual) showInfo() que exiba: <title> (<duration>s) - Type: <mediaType>. Esse método deve chamar getMediaType() para obter o tipo
    • Um destrutor virtual
  • Players.h: Implemente dois reprodutores de mídia concretos que herdem de MediaPlayer:

    AudioPlayer:

    • Um membro std::string artist privado
    • Um construtor que receba título, duração e artista
    • Implemente play() para exibir: Playing audio: <title> by <artist>
    • Implemente getMediaType() para retornar "Audio"

    VideoPlayer:

    • Um membro std::string resolution privado
    • Um construtor que receba título, duração e resolução
    • Implemente play() para exibir: Playing video: <title> in <resolution>
    • Implemente getMediaType() para retornar "Video"
  • main.cpp: Leia quatro entradas (cada uma em uma linha separada):
    1. Título da faixa de áudio
    2. Duração do áudio (inteiro)
    3. Título do vídeo
    4. Duração do vídeo (inteiro)

    Crie um AudioPlayer com o artista "Unknown Artist" e um VideoPlayer com a resolução "1080p". Armazene ambos em um array de ponteiros MediaPlayer*.

    Percorra o array e, para cada reprodutor, chame primeiro showInfo() e depois play(). Exiba uma linha em branco entre cada item de mídia. Libere os objetos alocados dinamicamente ao terminar.

Por exemplo, com as entradas Summer Vibes, 180, Nature Documentary e 3600:

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

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

Observe como o método showInfo() é definido uma vez na classe base abstrata, mas chama o método virtual puro getMediaType(). Isso demonstra como as classes abstratas podem combinar implementações concretas com métodos que as classes derivadas devem fornecer. Lembre-se de usar a palavra-chave override em todos os métodos sobrescritos.

Experimente você mesmo

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

int main() {
    // Ler 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: Crie um AudioPlayer com o artista "Unknown Artist"
    
    // TODO: Crie um VideoPlayer com a resolução "1080p"
    
    // TODO: Armazene ambos em um array de ponteiros MediaPlayer*
    
    // TODO: Percorra o array e para cada player:
    //       1. Chame showInfo()
    //       2. Chame play()
    //       3. Imprima uma linha em branco entre cada item de mídia
    
    // TODO: Limpe os objetos alocados dinamicamente
    
    return 0;
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C++ online