This is an old revision of the document!
Nous reprenons le code C++ de la partie précédente.
Ajoutez à la classe MyBiDiCounter l’ensemble des constructeurs dont notamment :
Modifier le code de la fonction testMyBiDiCounter
pour appeler le bon constructeur.
Sauvegarder votre projet pour pouvoir le réalisation dans la partie III du TD.
Dans la suite, nous vous conseillons de définir un nouveau projet utilisant une nouvelle copie des fichiers que vous avez réalisé, puisque nous allons partir de ce code à la fois dans les questions suivants mais aussi dans la partie III du TD.
La classe MyBiDiCounter
ajoute la fonction decrement
à la classe MyCounter
.
En fait, nous pouvons définir une famille de compteur :
ForwardCounter
qui compte de 0 à max et repars à 0.BackwardCounter
qui compte max à 9 et repars à max.BiDiCounter
qui peut incrémenter ou décrémenter le compteur interne.Nous souhaitons partager le maximum de code entre ces différents compteurs. Une solution consiste à définir l’arbre de dérivation suivant :
et nous souhaitons factoriser le maximum de code entre les classes ForwardCounter
, ReverseCounter
& BiDiCounter
, l’objectif étant que ces trois classes contiennent le minimum de code.
Faites la liste des méthodes, champs pouvant être partagés et la liste des méthodes et champs propres à chacune des classes.
Implanter la classe BaseCounter
. On s’inspirera fortement de la classe MyCounter
déjà définie.
Implanter les classes ForwardCounter
, BackwardCounter
et BiDiCounter
qui héritent chacune de la classe BaseCounter
.
Dans l'exemple précédent, nous constatons que nous définissons deux fois le code pour la fonction increment
et la fonction decrement
, ce qui conduit à dupliquer le code et surtout à devoir si jamais nous trouvons une erreur dans une des fonctions membres increment
(resp. decrement
) de devoir penser à corriger la deuxième implantation de la fonction membre increment
(resp. decrement
).
Dans ce cas, il est possible d'implanter les deux fonctions __increment'' et ''decrement
pour bien indiquer qu'il s'agit de fonction interne. Elles seront donc déclarées comme qui sont des fonctions internes à la classe et accessibles uniquement des classes dérivées. Ces fonctions contiennent le code de
increment et de
decrement, nous les avons préfixés par
%%protected
dans la classe BaseCounter
qui désormais s'écrira comme suit :
class BaseCounter { protected: unsigned counter; unsigned max; public: unsigned getCounter() const { return counter; } unsigned getMax() const { return max; } void reset() { counter = 0; } void set(unsigned value) { counter = value; } void setMax(unsigned value) { max = value; if(value > counter) counter = counter % max; } protected: BaseCounter(): counter(0), max(0) {} BaseCounterunsigned theCounter, unsigned theMax): counter(theCounter), max(theMax) {} BaseCounter (const BaseCounterunsigned & anotherCounter): counter(anotherCounter.counter), max(anotherCounter.max) {} ~BaseCounterunsigned () {} void __increment() { if(counter < max) counter = counter + 1; else counter = 0; } void __decrement() { if(counter > 0) counter = counter -1; else counter = max; } };
Il suffit désormais d'ajouter aux classes ForwardCounter
et BiDiCounter
la fonction :
public: void increment() { __increment(); }
ainsi qu'aux classes BackwardCounter
et BiDiCounter
la fonction ::
public: void decrement() { __decrement(); }
Ce qui nous donne le code suivant pour les trois classes dérivées :
class ForwardCounter: public BaseCounter { public: void increment() { __increment(); } ForwardCounter(): BaseCounter() {} ForwardCounter(const ForwardCounter& aCounter): BaseCounter(aCounter) {} explicit ForwardCounter(unsigned theMaxValue): ForwardCounter(0, theMaxValue) {} ForwardCounter(unsigned theCounter, unsigned theMaxValue): BaseCounter(theCounter, theMaxValue) {} }; class BackwardCounter: public BaseCounter { public: void decrement() { __decrement(); } BackwardCounter(): BaseCounter() {} BackwardCounter(const BackwardCounter& aCounter): BaseCounter(aCounter) {} explicit BackwardCounter(unsigned theMaxValue): BackwardCounter(0, theMaxValue) {} BackwardCounter(unsigned theCounter, unsigned theMaxValue): BaseCounter(theCounter, theMaxValue) {} }; class BiDiCounter: public BaseCounter { public: void increment() { __increment(); } void decrement() { __decrement(); } BiDiCounter(): BaseCounter() {} BiDiCounter(const BiDiCounter& aCounter): BaseCounter(aCounter) {} explicit BiDiCounter(unsigned theMaxValue): ForwardCounter(0, theMaxValue) {} BiDiCounter(unsigned theCounter, unsigned theMaxValue): BaseCounter(theCounter, theMaxValue) {} };
Tester le comportement de vos compteurs à partir du code suivant
void testFamilyOfCounters() { ForwardCounter incCounter(0, 4); BackwardCounter decCounter(0, 3); BiDiCounter biDiCounter(0, 5); for(int i=0; i < 6; i++) { incCounter.increment(); incCounter.print(); decCounter.decrement(); decCounter.print(); biDiCounter.increment(); biDiCounter.print(); } for(int i=0; i < 6; i++) { biDiCounter.decrement(); biDiCounter.print(); } }