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 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 pour bien indiquer qu'il s'agit de fonction interne. Elles seront donc déclarées comme protected dans la classe BaseCounter qui désormais s'écrira comme suit :
</hidden>
<code cpp>
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;
}
};
</code>
Il suffit désormais d'ajouter aux classes ForwardCounter et BiDiCounter la fonction :
<code cpp>
public:
void increment() { increment(); }
</code>
ainsi qu'aux classes BackwardCounter et BiDiCounter la fonction ::
<code cpp>
public:
void decrement() { decrement(); }
</code>
Ce qui nous donne le code suivant pour les trois classes dérivées :
<code cpp>
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) {}
};
</code>
</hidden>
=== Question n°3 ===
Tester le comportement de vos compteurs à partir du code suivant
<code cpp>
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();
}
}
</code>