This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
in204:tds:sujets:td2:part2 [2019/10/01 18:18] bmonsuez [Question n°2] |
in204:tds:sujets:td2:part2 [2022/11/18 10:49] (current) |
||
---|---|---|---|
Line 156: | Line 156: | ||
<hidden Correction 1 - Héritage Simple> | <hidden Correction 1 - Héritage Simple> | ||
+ | |||
+ | |||
Cette correction propose de créer trois classes ''ForwardCounter'', ''BackwardCounter'' et ''BiDiCounter'' qui héritent de la classe ''BaseCounter'' en l'étendant avec les fonctions manquantes : | Cette correction propose de créer trois classes ''ForwardCounter'', ''BackwardCounter'' et ''BiDiCounter'' qui héritent de la classe ''BaseCounter'' en l'étendant avec les fonctions manquantes : | ||
Line 350: | Line 352: | ||
* des fonctions ''getCounter'', ''getMax'', ''reset'' ''set'', ''setMax'' qui vont modifier les champs précédents ''BackwardCounter''->''BaseCounter''->''counter'' et ''BackwardCounter''->''BaseCounter''->''max'', nous allons identifier ces fonctions par leur chemin d'accès ''BackwardCounter''->''BaseCounter''->''getCounter'', ... | * des fonctions ''getCounter'', ''getMax'', ''reset'' ''set'', ''setMax'' qui vont modifier les champs précédents ''BackwardCounter''->''BaseCounter''->''counter'' et ''BackwardCounter''->''BaseCounter''->''max'', nous allons identifier ces fonctions par leur chemin d'accès ''BackwardCounter''->''BaseCounter''->''getCounter'', ... | ||
* une fonctions ''decrement'' qui va modifier le champ ''BackwardCounter''->''BaseCounter''->''counter''. | * une fonctions ''decrement'' qui va modifier le champ ''BackwardCounter''->''BaseCounter''->''counter''. | ||
- | </hidden> | ||
Ceci signifie que nous avons deux instances des champs ''max'' et ''counter'' en fonction de l'héritage : | Ceci signifie que nous avons deux instances des champs ''max'' et ''counter'' en fonction de l'héritage : | ||
Line 362: | Line 363: | ||
La solution serait que ''ForwardCounter'' et ''BackwardCounter'' ne crée pas chacun une instance de ''BaseCounter'' mais hérite de la même instance de ''BaseCounter''. Le schéma d'héritage deviendrait alors celui-ci : | La solution serait que ''ForwardCounter'' et ''BackwardCounter'' ne crée pas chacun une instance de ''BaseCounter'' mais hérite de la même instance de ''BaseCounter''. Le schéma d'héritage deviendrait alors celui-ci : | ||
- | |||
- | |||
- | |||
Pour ce faire, les classes ''ForwardCounter'' et ''BackwardCounter'' vont faire référence à une même instance de la classe de base qui sera crée par l'objet qui héritera des classes ''ForwardCounter'' et ''BackwardCounter''. | Pour ce faire, les classes ''ForwardCounter'' et ''BackwardCounter'' vont faire référence à une même instance de la classe de base qui sera crée par l'objet qui héritera des classes ''ForwardCounter'' et ''BackwardCounter''. | ||
Line 432: | Line 430: | ||
ForwardCounter(): BaseCounter() {} | ForwardCounter(): BaseCounter() {} | ||
</code> est ignorée. Cette partie n"est active que quand on crée un objet de type ''ForwardCounter'' (resp. ''BackwardCounter'') et non pas un objet dérivé de ''ForwardCounter'', (resp ''BackwardCounter''). | </code> est ignorée. Cette partie n"est active que quand on crée un objet de type ''ForwardCounter'' (resp. ''BackwardCounter'') et non pas un objet dérivé de ''ForwardCounter'', (resp ''BackwardCounter''). | ||
- | + | - Affectation à chacun des instances de ''ForwardCounter'' et de ''BackwardCounter'' d'une référence à l'objet ''BaseCounter'' qui a été créé. | |
- | - Et enfin, affectation à chacun des instances de ''ForwardCounter'' et de ''BackwardCounter'' d'une référence à l'objet ""BaseCounter'' qui a été créé. | + | |
Ce processus garantit que les instances ''ForwardCounter'' et ''BackwardCounter'' feront référence à une seule et unique instance ''BaseCounter''. | Ce processus garantit que les instances ''ForwardCounter'' et ''BackwardCounter'' feront référence à une seule et unique instance ''BaseCounter''. | ||
+ | |||
+ | De ce fait, le code pour la classe ''BiDiCounter'' devient le suivant : | ||
+ | <code cpp> | ||
+ | class BiDiCounter: public ForwardCounter, public BackwardCounter | ||
+ | { | ||
+ | public: | ||
+ | BiDiCounter(): ForwardCounter(), BackwardCounter() {} | ||
+ | BiDiCounter(const BiDiCounter& aCounter): | ||
+ | ForwardCounter(aCounter), | ||
+ | BackwardCounter((const BackwardCounter&)aCounter), | ||
+ | BaseCounter(aCounter) {} | ||
+ | BiDiCounter(unsigned theMaxValue): BiDiCounter(0, theMaxValue) {} | ||
+ | BiDiCounter(unsigned theCounter, unsigned theMaxValue): | ||
+ | ForwardCounter(), | ||
+ | BackwardCounter(), | ||
+ | BaseCounter(theCounter, theMaxValue) {} | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | Ceci permet de comprendre que l'héritage multiple est intéressant conceptuellement, puisqu'il permet d'hériter de plusieurs comportements. Cependant, sa mise en oeuvre est relativement simple pour des cas où les classes dont on hérite ne dérivent pas d'une même classe de base. Si c'est le cas, il faut recourir à un héritage faisant référence aux classes qui est nettement moins intuitif et peut même conduire à des erreurs. En effet, il est nécessaire de créer l'instance qui sera partagée entre les différentes classes et à défaut de création explicite, s'il existe un constructeur par défaut, C++ utilisera ce constructeur par défaut pour initialiser l'objet partagé, même si ce n'était pas votre souhait mais simplement un oubli de votre part. | ||
+ | |||
+ | </hidden> | ||
===== Question n°3 ===== | ===== Question n°3 ===== | ||
Line 463: | Line 482: | ||
} | } | ||
</code> | </code> | ||
+ | |||
+ | <hidden Correction> | ||
+ | Il suffit de tester les codes et de s'assurer du bon fonctionnement. | ||
+ | </hidden> | ||