User Tools

Site Tools


in204:cpp:syntax:class:deriving

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
in204:cpp:syntax:class:deriving [2019/09/23 20:26]
bmonsuez [Déclare une classe dérivée]
in204:cpp:syntax:class:deriving [2022/11/18 10:51] (current)
Line 1: Line 1:
-====== ​La classe ​dérivée ======+====== ​Classe ​dérivée ​& héritage ​======
  
-La classe dérivée est une **extension** ​d'une classe ​de base. C'est une classe à laquelle on a ajouté des __champs__ et des __fonctions membres__ supplémentaires.+===== Pourquoi hériter ​d'une classe ​====
  
-La classe dérivée ''​hérite''​ de l'​ensemble des __fonctions membres__ et des __champs__ définis par la ou les classes de bases. C'est pour cela que l'on parle d'​héritage quand on parle de classes dérivées d'une autre classe.+Supposons ​que nous avons réaliser un objet qui effectuer une certaine tâche ​de base
  
-===== Déclare ​une classe dérivée ​====+<code cpp> 
 +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; 
 +  } 
 +
 +</​code>​ 
 + 
 +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.
  
-La syntax pour déclarée une classe comme héritant d'une classe de base est la suivante : 
 <code cpp> <code cpp>
 +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 DerivingClasspublic BaseClass+class bidi_enumerate_charactersenumerate_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();​ 
 +  } 
 +
 +</​code>​
  
 +La classe ''​bidi_enumerate_characters''​ est une extension de la classe ''​enumerate_characters''​ :
 +
 +<code cpp>
 +class bidi_enumerate_characters:​ enumerate_characters
 +{
 </​code>​ </​code>​
  
-Cette définition indique que la classe ''​DerivingClass''​ hérite de la classe ''​BaseClass''​ et donc que l'​ensemble ​des méthodes et des champs ​définis par la classe ''​BaseClass''​ sont présents dans la classe ''​DerivingClass''​. ​Cependantil faut faire attention, présent ​ne veut pas dire qu'​ils ​sont accessibles ​dans la classe de baseAinsi, nous avons les règles d'accessibilité suivantes pour les méthodes ​et les champs définis ​dans la classe de base.+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''​. ​Attentionles 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''​ :
  
-^ Déclaration dans la classe de base ^ Accesibilité dans la classe dérivée ^ +<code cpp> 
-|les champs ou méthodes déclarés ''​public''​ dans la classe de base | les champs et méthodes sont accessibles dans la classe dérivée | +class enumerate_characters 
-|les champs ou méthodes déclarés ''​protected''​ dans la classe de base | les champs et méthodes sont accessibles dans la classe dérivée | +{ 
-|les champs ou méthodes déclarés ''​private''​ dans la classe de base | les champs et méthodes ne sont pas accessibles dans la classe dérivée |+private
 +  int mPosition;​ 
 +protected:​ 
 +  int mNumberOfCharacters;​ 
 +  const char* mString; 
 +public: 
 +</​code>​
  
-Cependantil faut aussi s'intéresser ​à l'accesibilité ​des méthodes ​en dehors ​de la classe ​dérivée. C'​est ​ici qu'intervient ​les attributs d'accessibilité ​que l'on place devant ​le type de la classe ​dont hérite qui peuvent ​être ''​public'',​ ''​protected'' ​ou ''​private''​.+Nous voyons que la classe ''​bidi_enumerate_characters''​ ajoute la fonction ''​previous()''​ à la classe de base. 
 + 
 +<code cpp> 
 +  int previous() 
 +  { 
 +      return mReversePosition >= 0 ?  
 +        (int)mString[mPosition++] : -1; 
 +  } 
 +</​code>​ 
 + 
 +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.  
 + 
 +Ensuitenous constatons que la classe ''​bidi_enumerate_characters''​ rédéfinit la méthode ''​reset()''​ : 
 + 
 +<code cpp> 
 +  void reset() 
 +  { 
 +      mReversePosition= mNumberOfCharacters;​ 
 +      enumerate_characters()::​reset();​ 
 +  } 
 +</​code>​ 
 + 
 +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]] 
 + 
 + 
 +===== Déclarer des champs dans une classe dérivée ===== 
 + 
 +Les champs qui sont déclarés dans une classe dérivée ne peuvent pas avoir le même nom que les champs dans une des classes de base. 
 + 
 +===== Déclarer ​des méthodes ​dans une classe dérivée ===== 
 + 
 +__**Cas 1**: La méthode ''​method''​ a un nom différent ​de celui des méthodes existance dans la classe ​de base.__ 
 + 
 +C'​est ​par exemple le cas de la méthode ​''​previous()''​ dans la classe ''​bidi_enumerate_characters''​ : 
 +<code cpp> 
 +  int previous() 
 +  { 
 +      return mReversePosition >= 0 ?  
 +        (int)mString[mPosition++] : -1; 
 +  } 
 +</​code>​ 
 + 
 +Ce sont les règles habituelles de la déclaration des méthodes dans les classes. La nouvelle méthode s'ajoute aux anciennes méthodes. 
 + 
 +__**Cas 2**: La méthode ''​method''​ a le même nom que celui des méthodes existance dans la classe de base.__ 
 + 
 +C'est par exemple ​le cas de la méthode ''​reset()''​ dans la classe ​''​bidi_enumerate_characters''​ : 
 +<code cpp> 
 +  void reset() 
 +  { 
 +      mPosition = 0; 
 +      enumerate_characters()::​reset();​ 
 +  } 
 +</​code>​ 
 + 
 +**Règle 1**: Si nous définissons une ou plusieurs méthodes ayant le nom ''​method''​ et que des méthodes ayant le même nom ont été définies dans la classe de base, les méthodes ayant comme nom ''​method''​ sont cachées dans la classe de base.  
 + 
 +<code cpp> 
 +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 extended_enumerate_characters:​ enumerate_characters 
 +
 +public: 
 +  extended_enumerate_characters(const char* aString, int theNumberOfCharacters):​ 
 +      enumerate_characters(aString,​ theNumberOfCharacters) {} 
 +   
 +  int next(int lookup) 
 +  { 
 +      mPosition += increment;​ 
 +      if(mPosition >= mNumberOfCharacters) 
 +      { 
 +          mPosition = mNumberOfCharacters;​ 
 +          return (int)-1; 
 +      } 
 +      return (int)mString[mPosition++];​ 
 +  } 
 +
 +</​code>​ 
 + 
 +Dans ce cas, la méthode ''​next(int)''​ va être la seule méthode visible dans la classe  ​''​extended_enumerate_characters''​. La méthode ''​next()''​ de la classe ''​enumerate_characters''​ mais elle sera masquée et sera donc inaccessible. 
 + 
 +**Règle 2**: Il est possible de rendre visible dans la classe dérivée les méthodes qui ont été définies dans la classe de base est qui ne prennent pas les même arguments que celles définies dans la classe dérivée. 
 + 
 +Si nous voulons rendre la méthode ''​next()''​ visible, il faudra ajouter à la classe ''​extended_enumerate_characters''​ la directive : ''​using enumerate_characters::​next''​ pour indiquer que les méthodes ayant pour nom ''​next''​ et étant définie dans la classe de base sont aussi visible dans la classe dérivée. 
 +<code cpp> 
 +class extended_enumerate_characters:​ enumerate_characters 
 +
 +public
 +  extended_enumerate_characters(const char* aString, int theNumberOfCharacters):​ 
 +      enumerate_characters(aString,​ theNumberOfCharacters) {} 
 + 
 +  using enumerate_characters::​next;​ 
 +  int next(int lookup) 
 +  { 
 +      mPosition += increment;​ 
 +      if(mPosition >= mNumberOfCharacters) 
 +      { 
 +          mPosition = mNumberOfCharacters;​ 
 +          return (int)-1; 
 +      } 
 +      return (int)mString[mPosition++];​ 
 +  } 
 +
 +</​code>​ 
 + 
 +Dans la classe ''​extended_enumerate_characters'', ​les deux méthodes ​''​enumerate_characters::​next()'' ​et  
 +''​extended_enumerate_characters::​next(int)'' ​sont accessibles.  
 + 
 +<code cpp> 
 +    extended_enumerate_characters enumerator("​abcdefg"​);​ 
 +    std::cout << enumerator.next(2);​ 
 +    std::cout << enumerator.next(); 
 +</​code>​
  
-^ Attribut d'​héritage ^ Accessibilité en dehors de la classe ​^ Accessibilité dans une classe dérivant de ''​DerivingClass'' ​+Par contre, dans la classe ''​bidi_enumerate_characters''​, ajouter ​''​using enumerate_characters:​:reset'' ​ne sert à rien parce que la fonction ​''​reset()'' ​dans la classe dérivée à la [[cpp::syntax::​functions::​overload|même signature]] que la fonction ​''​reset'' ​dans la classe ​de base.
-|''​DerivingClasspublic BaseClass''​| Les méthodes et champs ​''​public'' ​de ''​BaseClass''​ sont accessibles. | +
-Les méthodes et champs ''​public''​ ou ''​protected''​ de ''​BaseClass''​ sont accessibles à la classe dérivée. | +
-|''​DerivingClass:​ private BaseClass''​| Aucune méthode ou champs de ''​BaseClass''​ sont accessibles. | +
-Aucune méthode ou champs de ''​BaseClass''​ sont accessibles ​à la classe dérivée. | +
-|''​DerivingClassprotected BaseClass''​Aucune méthode ou champs de ''​BaseClass'' ​sont accessibles. | +
-Les méthodes et champs ''​public''​ ou ''​protected''​ de ''​BaseClass''​ sont accessibles à la classe ​dérivée|+
  
in204/cpp/syntax/class/deriving.1569270405.txt.gz · Last modified: 2019/09/23 20:26 by bmonsuez