next up previous contents
Next: Héritage multiple Up: Héritage simple Previous: Constructions des objets dérivés

De la classe dérivée à la classe de base

Comme conséquence de cette notion d'héritage, on pourra toujours considérer un objet d'une classe dérivée comme un objet d'une classe de base. C'est vrai en particulier pour les pointeurs et les références.

Mais attention, si la conversion de classe dérivée vers classe de base ne pose aucun problème (car un objet de la classe dérivée c'est un objet de la classe de base plus quelque chose), de la classe de base vers la classe dérivée, la conversion ne peut pas être automatique, car en général, le ``quelque chose'' en plus de la classe dérivée risque de ne pas être alloué.

classe base{
  int i;
};
classe derivee{
  int j;
};
void essai(){
  base b;
  derivee d;
  base *pb;
  derivee *pd;
  // a priori sizeof(b)==sizeof(int)
  // et  sizeof(d)==2*sizeof(int)
  b=d;   // ok d est un base
  d=b;   // non 
  pb=&d; // ok
  pd=&b; // non ou se trouve pd->j ??
};

Cependant, comme on le verra dans le paragraphe concernant la liaison dynamique, l'affectation de pointeur ou de référence n'est pas identique à l'affectation d'objets : pour l'affectation b=d;, seule la partie base (c'est-à-dire uniquement les données membres de la partie base) sera copiéegif, alors que dans l'affectation de pointeur pb=&d; pb sera initialisé par l'adresse de la partie base de d. En ce sens, pb bien qu'étant défini comme un pointeur sur base est en fait un pointeur sur derivee.

On peut définir des constructeurs permettant de convertir un objet d'une classe dérivée vers une classe de base ou d'une classe de base vers une classe dérivée :

class derive;
class base{
protected:
   int i;
public: //...
   base(const base&);       // constructeur de copie
   base();                  // constructeur par defaut
   base(const derive &);    // conversion derive->base
};
class derive: public base{
protected:
   int j;
   base::i;
public: //...
   derive(const base &);   // conversion base->derive
};
base::base(const derive & d){ /*...*/};
//...
base b1;
derive d1=b1; 
base b2=d1;
derive d1=b1; appellera derive(const base &), et base b2=d1; appellera base(const derive &). (Si ce constructeur n'avait pas été défini, base b2=d1; aurait appelé le constructeur de copie base(const base&).

Notons enfin, qu'un cast explicite peut convertir une adresse d'objet d'une classe de base en une adresse d'objet d'une classe dérivée (avec les risques éventuels que cela implique.




Mon Oct 20 14:02:48 MET 1997