next up previous contents
Next: Conversions Up: Initialisation et constructeurs Previous: Création : quand?

Constructeur de copie et initialisation membre à membre

On peut définir un constructeur particulier qui permet de copier un objet de la classe; un tel constructeur pour la classe X aura la forme X::X(X&) ou X::(const X&) (et éventuellement d'autres arguments). Cet opérateur de copie permet, par exemple, de réaliser des copies profondes :

// chaines avec copie profonde
class chaine{
public:
  chaine(const char *s){
    lg=strlen(s);
    ch= new char [lg +1]; 
    assert(ch != 0);
    ch=strcpy(ch,s);
  };
  // ...
  chaine(const chaine&);
  // ...
  ~chaine(){delete [] ch;} 
private:
  char *ch;
  int lg;
};
chaine::chaine(const chaine &c){
  lg=c.lg;
  ch= new char [lg+1];
  assert(ch != 0);
  ch=strcpy(ch,c);
}

Si ce constructeur de copie n'était pas défini, le constructeur par défaut ferait une copie de chaque donnée membre, et la donnée membre ch du nouvel objet pointerait sur la même adresse que l'ancien (ce qui pourrait poser des problèmes si un des deux objets libérait la mémoire associéegif...).

Il ne faut pas confondre la copie et l'affectation:

X a;
X a=b; // constructeur de copie
a=b;   // affectation

Quand un objet d'une classe est initialisé par un autre objet de la classe, le constructeur de copie est appelé. Si aucun constructeur de copie n'a été défini par l'utilisateur de la classe, on utilise un constructeur de copie par défaut qui réalise une copie membre à membre.

Plus généralement, le constructeur de copie est appelé par le compilateur chaque fois que l'on doit initialiser un objet de la classe par un autre objet de la classe; par exemple:

Exemple:
class X{
  //...
public:
  X(const &X);//...
};
X a;                   // X::X()
X a=b;                 // X::X(a)
void fv(X x){/*...*/}
void fr(X& x){/*...*/}
X gv(int i){/*...*/}
X& gr(int i){/*...*/}
void f(){
  X c;
  //...
  fv(a);              // fv(X::X(a))
  fr(a);              // passage par reference
  c=gv(2);            // appel de X::X(X&) pour le resultat
  gr(1)=c;            // pas d'appel de X::X(X&)
}

Comme on peut le remarquer, le constructeur de copie ne concerne pas les passages par références (ni, bien sûr, les pointeurs) car ce type de passage ne provoque pas la création d'une copie locale de l'objet. Par contre dans le passage de références ou de pointeur une conversion de pointeurs peut avoir lieu et permettra la liaison dynamique.




Mon Oct 20 14:02:48 MET 1997