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 :
<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>