====== Classe dérivée & héritage ====== ===== Pourquoi hériter d'une classe ==== Supposons que nous avons réaliser un objet qui effectuer une certaine tâche de base. class enumerate_characters { private: int mPosition; int mNumberOfCharacters; const char* mString; public: enumerate_characters(const char* aString, int theNumberOfCharacters): mString(aString), mNumberOfCharacters(theNumberOfCharacters) {} int next() { return mPosition < mNumberOfCharacters ? (int)mString[mPosition++] : -1; } void reset() { mPosition = 0; } } Cette classe énumère les caractère de la chaîne de caractère passée en paramètre en commençant par le premier caractère et en terminant par le dernier caractère. Supposant que je ne souhaite plus énumérer les caractères en commençant par le premier caractère et en terminant par le dernier caractère mais à l'inverse en commençant par le dernier caractère et en terminant par le premier. Je devrais ajouter à cette classe la fonction ''previous()'' par exemple. Je peux soit ajouter cette méthode dans la classe ou au contraire ajouter cette méthode à une extension de la classe, ce que l'on appelle une classe dérivée ou une classe fille qui hérite de son parent. L'intérêt est dans ce cas que je vais pouvoir modifier le comportement de la classe. class enumerate_characters { private: int mPosition; protected: int mNumberOfCharacters; const char* mString; public: enumerate_characters(const char* aString, int theNumberOfCharacters): mString(aString), mNumberOfCharacters(theNumberOfCharacters) {} int next() { return mPosition < mNumberOfCharacters ? (int)mString[mPosition++] : -1; } void reset() { mPosition = 0; } } class bidi_enumerate_characters: enumerate_characters { private: int mReversePosition; public: bidi_enumerate_characters(const char* aString, int theNumberOfCharacters): enumerate_characters(aString, theNumberOfCharacters), mReversePosition(theNumberOfCharacters) {} int previous() { return mReversePosition >= 0 ? (int)mString[mPosition++] : -1; } void reset() { mReversePosition= mNumberOfCharacters; enumerate_characters()::reset(); } } La classe ''bidi_enumerate_characters'' est une extension de la classe ''enumerate_characters'' : class bidi_enumerate_characters: enumerate_characters { ce qui veut que l'ensemble des champs et méthodes présents dans la classe ''enumerate_characters'' sont présents dans la classe ''bidi_enumerate_characters''. Attention, les champs ou méthodes privées sont présentes mais ne sont pas accessibles. Ici, nous avons besoin des champs ''mNumberOfCharacters'' et ''mString'' dans la classe dérivée, c'est pour cela que nous avons modifié la classe de base ''enumerate_characters'' pour les rendre toujours inaccessibles en dehors de la classe mais accessible dans les classes derivées en les déclarant comme ''proctected'' : class enumerate_characters { private: int mPosition; protected: int mNumberOfCharacters; const char* mString; public: Nous voyons que la classe ''bidi_enumerate_characters'' ajoute la fonction ''previous()'' à la classe de base. int previous() { return mReversePosition >= 0 ? (int)mString[mPosition++] : -1; } c'est pour cela qu'on dit qu'une classe dérivée est une extension de la classe de base par ce qu'elle peut ajouter des fonctions et des comportements. Ensuite, nous constatons que la classe ''bidi_enumerate_characters'' rédéfinit la méthode ''reset()'' : void reset() { mReversePosition= mNumberOfCharacters; enumerate_characters()::reset(); } En effet, lorsque nous appellons la méthode ''reset()'', nous mettons d'abord le champs ''mReversePosition'' à ''mNumberOfCharacters'' et puis ensuite nous appellons la méthode ''reset()'' de la classe de base ''enumerate_characters()::reset()''. Nous avons spécialisé le comportement de la fonction ''reset()'' par rapport à la fonction ''reset()'' de la classe de base. C'est pour cela que les classes dérivées sont aussi appellées classes spécialisées. [[cpp:syntax:class:deriving:creating|Définir une classe dérivée]] [[cpp:syntax:class:deriving:methods|Définir champs et méthodes dans une classe dérivée]] [[cpp:syntax:class:deriving:constructor|Définir les constructeurs dans une classe dérivée]] [[cpp:syntax:class:deriving:destructor|Définir les destructeurs dans une classe dérivée]]