TD 10 C++: Polymorphisme, suite et fin.

Rappels


Exercice 0: Poymorphisme, encore un peu

Note: j'ai beaucoup aimé la page sur le polymorphisme de cplusplus.com. à lire si vous êtes perdu. Mais attention, l'exo 1 ci-dessous est encore plus tordu! Bonne chance.
  1. Entrez dans un fichier 0.1.txt ce que le code ci-dessous (sur 2 colonnes) affiche quand il est exécuté.

    screenshot d'un code à examiner: colonne de gauche screenshot d'un code à examiner: colonne de droite
    Exemple de contenu de 0.1.txt:
    ABCDEF
    G
    HI
    JKL
    MNOP
    QRSTU
    Vérifiez avec le script 0.1.sh:
    bash 0.1.sh
    RENDU: 0.1.txt

  2. Que se passe-t'il si on ajoute la ligne suivante a la fin de main()?
    ((B*)(&a))->X();
    RENDU: 0.2.txt avec une description très très succinte de ce qui se passe, et une mini explication.


Exercice 1: Fonctions abstraites

Faites le 2 avant le 1!

  1. Téléchargez 1.1.h (copié ci-dessous) et complétez-le, et implémentez les classes dans un fichier 1.1.cc.
    class Sequence {
     public:
      // The value of the sequence at the current step.
      double Value();
    
      // Advances to the next step.
      void Next();
    };
    
    // 1, 1, 2, 3, 5, 8, ...
    class FibonacciSequence : public Sequence {
    };
    
    // 1, 1, 2, 6, 24, 120, 720, ... modulo x: if x = 10, that's
    // 1, 1, 2, 6, 4, 0, 0, ...
    class FactorialModXSequence : public Sequence {
     public:
      explicit FactorialModXSequence(int x);
    };
    Veillez à rendre les fonctions de la classe de base Sequence abstraites.

    Testez votre code avec 1.tar.gz:
    rm 1.tar.gz; wget --no-cache http://fabien.viger.free.fr/cpp/td10/1.tar.gz
    tar xf 1.tar.gz
    make 1.1
    RENDU: 1.1.h et 1.1.cc

  2. Copiez 1.1.h et 1.1.cc dans 1.2.h et 1.2.cc.
    Ensuite, Créez une classe ShiftSequence, sous-classe de Sequence, dont le constructeur prendra en argument une Sequence* arbitraire seq et un décalage (entier positif) shift, telle que:
    ShiftSequence(seq, shift)n = seqseq0 + n + shift, où seq0 est l'étape initiale de seq quand on a construit l'objet ShiftSequence.

    Le passage de seq se fera par pointeur, et la classe ShiftSequence prendra possession de l'objet seq donné: c'est lui qui devra se charger de sa suppression.

    Subtilité supplémentaire: contrairement au reste des Sequence donnés jusqu'à présent, vos objets ShiftSequence ne peuvent pas être copiés "naturellement" sans créer des problèmes. Empêchez la copie d'un ShiftSequence vers un autre! Ma solution préférée est la 3ème méthode citée ici.

    Testez votre code avec
    make 1.2
    RENDU: 1.2.h et 1.2.cc

  3. Copiez 1.2.h et 1.2.cc dans 1.3.h et 1.3.cc.
    Ensuite, ajoutez une fonction int Step() qui renvoie l'étape courante d'une Sequence (elle renverra 0 au début). Pour ne pas avoir à la redéfinir pour chaque sous-classe de Sequence, on va utiliser une astuce:
    Testez votre code avec
    make 1.3
    RENDU: 1.3.h et 1.3.cc

Exercice 2: Un exemple acceptable de polymorphisme

  1. Teléchargez l'archive 2.tar.gz et extrayez son contenu:
    tar xf 2.tar.gz
    Télechargez et complétez les fichier 2.1.h et 2.1.cc.
    Testez votre code avec:
    make 2.1
    Indice important: vous aurez sans doute une erreur parlant de non-virtual destructor. Pour la réparer, vous devrez retoucher 2.1.h mais attention vous n'avez que le droit d'y ajouter une seule ligne!

    RENDU: 2.1.h et 2.1.cc

  2. Copiez 2.1.h et 2.1.cc dans des fichiers 2.2.h et 2.2.cc.
    Ajoutez une classe Circle, dont le nom (donné par Name()) sera Circle, en suivant le même principe que StraightSquare.
    Pour construire un cercle, on donne typiquement les coordonées (x, y) de son centre, et son rayon.

    Testez votre code avec:
    make 2.2
    RENDU: 2.2.h et 2.2.cc

  3. Copiez 2.2.h et 2.2.cc dans des fichiers 2.3.h et 2.3.cc.
    Ajoutez la fonction polymorphique Perimeter() à la classe Shape. Elle devra renvoyer 0 pour la classe de base. Bien sûr, vous devrez l'implementer dans les classes dérivées.
    Ajoutez la chaine: , perimeter=<perimeter>" à la fonction Description() (attention à la virgule avant perimeter=!).

    Testez votre code avec:
    make 2.3
    RENDU: 2.3.h et 2.3.cc