This is an old revision of the document!
Une classe dérivée :
Lors de la création d'un nouvel objet, nous avons deux phases :
Les constructeurs définis pour chacune des classes de base ne disposent pas des informations nécessaires pour pouvoir initialiser les champs dans la classe étendue.
Il est donc nécessaire de définir un nouveau constructeur qui va :
La syntaxe d'un constructeur d'une classe dérivée appelant les constructeurs de la classe de base est la suivante :
class Cloth { public: enum Size { S, M, L, XL, XXL, XXXL }; private: Size m_size; public: Size getSize() const { return m_size; } protected: Cloth(): m_size(Cloth::S); explicit Cloth(Size theSize): m_size(theSize) {} Cloth(const ClothBase& theSource): m_size(theSource.theSize) {} }; public class Pant: Cloth { private: unsigned m_length; public: Pant(Cloth::Size theSize, unsigned theLength): Cloth(theSize), m_length(theLength) {} Pant(unsigned theLength): m_length(theLength) {} Pant(const Pant& anotherPant): Cloth(anotherPant), m_lentgh(anotherPant.m_length) {} };
Dans le code précédent, Pant
définit un nouveau constructeur Pant(Cloth::Size, unsigned)
qui va appelé tout d'abord le constructeur Cloth(Cloth::Size)
pour initialiser la classe de base et ensuite procéder à l'initialisation du champ défini dans Pant
avec la valeur passée au paramètre theLength
.
Si nous souhaitons inversé l'odre d'initialisation, nous aurions du écrire :
Pant(Cloth::Size theSize, unsigned theLength): m_length(theLength), Cloth(theSize) {}
Dans ce cas de figure, la première opération consiste à initialisé le champs défini dans Pant
et ensuite d'appelé le constructeur Cloth(Cloth::Size)
pour initialiser la classe de base. Ceci peut avoir une importance quand l'initialisation d'un champ ou d'une classe requiert que la valeur définie pour un autre champ ou une autre classe soit déjà effectuée.
Considérons désormais la déclaration du constructeur Pant(unsigned)
. Ce constructeur se contente d'initialiser le champ m_length
. Il n'y a pas d'appel à un constructeur de la classe de base.
Pant(unsigned theLength): m_length(theLength) {}
Mais il est nécessaire d'initialiser intégralement les extensions mais aussi la classe de base. Si aucun constructeur n'est appelé, C++ initialise la classe de base en appelant le constructeur par défaut. En fait, le code précédent est équivalent au code suivant :
Pant(unsigned theLength): m_length(theLength), Cloth() {}
Ceci permet de garantir que l'ensemble des champs est bien initialisé par le constructeur.