Menu
Coddy logo textTech

Classes abstraites

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 60 sur 104.

Une classe abstraite est toute classe qui contient au moins une fonction virtuelle pure. Comme son interface est incomplète, vous ne pouvez pas créer directement des objets d’une classe abstraite : elle existe uniquement pour être héritée.

class Shape {
public:
    virtual double area() = 0;      // Virtuelle pure - rend Shape abstrait
    virtual double perimeter() = 0; // Une autre fonction virtuelle pure
    
    void printInfo() {              // Méthode ordinaire - a une implémentation
        std::cout << "Area: " << area() << std::endl;
    }
    
    virtual ~Shape() = default;
};

Shape s;  // Erreur : impossible d'instancier une classe abstraite

Les classes abstraites peuvent contenir un mélange de fonctions virtuelles pures (sans implémentation), de fonctions virtuelles ordinaires (avec une implémentation par défaut) et de fonctions non virtuelles. Cela vous permet de définir un comportement commun tout en exigeant des classes dérivées qu’elles implémentent des fonctionnalités spécifiques.

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 implémente toutes les fonctions virtuelles pures
c.printInfo();      // Utilise printInfo() héritée, appelle area() de Circle

Une classe dérivée doit implémenter toutes les fonctions virtuelles pures pour devenir concrète (instanciable). Si elle en laisse certaines non implémentées, elle reste elle-même abstraite. Ce mécanisme garantit que chaque classe concrète de votre hiérarchie fournit les fonctionnalités requises.

challenge icon

Défi

Facile

Construisons un système de lecteur multimédia qui montre comment les classes abstraites définissent des contrats pour différents types de médias. Vous allez créer une classe de base abstraite qui établit ce que chaque lecteur multimédia doit faire, puis implémenter des lecteurs concrets pour le contenu audio et vidéo.

Vous allez organiser votre code sur trois fichiers :

  • MediaPlayer.h : définir une classe abstraite MediaPlayer qui sert de modèle pour tous les types de médias. Votre classe abstraite doit comporter :
    • Un membre protégé std::string title
    • Un membre protégé int duration (en secondes)
    • Un constructeur qui initialise les deux valeurs
    • Une méthode virtuelle pure play() : chaque type de média sera lu différemment
    • Une méthode virtuelle pure getMediaType() qui renvoie un std::string
    • Une méthode ordinaire (non virtuelle) showInfo() qui affiche : <title> (<duration>s) - Type: <mediaType>. Cette méthode doit appeler getMediaType() pour obtenir le type
    • Un destructeur virtuel
  • Players.h : implémenter deux lecteurs multimédias concrets qui héritent de MediaPlayer :

    AudioPlayer :

    • Un membre privé std::string artist
    • Un constructeur prenant le titre, la durée et l’artiste
    • Implémenter play() pour afficher : Playing audio: <title> by <artist>
    • Implémenter getMediaType() pour renvoyer "Audio"

    VideoPlayer :

    • Un membre privé std::string resolution
    • Un constructeur prenant le titre, la durée et la résolution
    • Implémenter play() pour afficher : Playing video: <title> in <resolution>
    • Implémenter getMediaType() pour renvoyer "Video"
  • main.cpp : lire quatre entrées (chacune sur une ligne distincte) :
    1. Titre de la piste audio
    2. Durée audio (entier)
    3. Titre de la vidéo
    4. Durée de la vidéo (entier)

    Créer un AudioPlayer avec l’artiste "Unknown Artist" et un VideoPlayer avec la résolution "1080p". Stocker les deux dans un tableau de pointeurs MediaPlayer*.

    Parcourir le tableau et, pour chaque lecteur, appeler d’abord showInfo(), puis appeler play(). Afficher une ligne vide entre chaque élément multimédia. Libérer les objets alloués dynamiquement une fois terminé.

Par exemple, avec les entrées Summer Vibes, 180, Nature Documentary et 3600 :

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

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

Remarquez comment la méthode showInfo() est définie une seule fois dans la classe de base abstraite, mais appelle la méthode virtuelle pure getMediaType(). Cela montre comment les classes abstraites peuvent combiner des implémentations concrètes avec des méthodes que les classes dérivées doivent fournir. N’oubliez pas d’utiliser le mot-clé override pour toutes les méthodes redéfinies.

Essayez vous-même

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

int main() {
    // Lire les entrées
    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: Créer un AudioPlayer avec l'artiste "Unknown Artist"
    
    // TODO: Créer un VideoPlayer avec la résolution "1080p"
    
    // TODO: Stocker les deux dans un tableau de pointeurs MediaPlayer*
    
    // TODO: Parcourir le tableau et pour chaque player :
    //       1. Appeler showInfo()
    //       2. Appeler play()
    //       3. Afficher une ligne vide entre chaque élément multimédia
    
    // TODO: Nettoyer les objets alloués dynamiquement
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne