Mini-Référence :
Introduction à la POO : Constructeur et Destructeur
Surcharge d'opérateurs
L'opérateur ::
Lorsque les définitions des classes deviennent complexes, il est
intéressant de pouvoir simplifier l'écriture des
déclarations. C'est (en partie) le rôle de l'opérateur de
résolution de portée :: qui permet ainsi
d'écrire les
définitions des méthodes d'une classe à l'extérieur de
la déclaration de la classe. À l'aide de ::
le programmeur
peut se contenter d'indiquer les prototypes des méthodes
dans la déclaration de la classe et donner les définitions
correspondantes, à l'extérieur de la déclaration, sous la forme de
définition de fonctions de nom :
nom_classe::nom_fonction
Constructeurs et destructeurs
Les constructeurs et destructeurs sont des méthodes
particulières, qui sont invoquées respectivement à la création et à la
destruction d'un objet. Toute classe a (au moins) un constructeur et
un destructeur, par défaut fourni par le compilateur (dans ce cas, ces
constructeurs et destructeurs sont extrêmement basiques, et se
contentent d'initialiser ou détruire les attributs pour lesquels ces
opérations ont un sens). En conséquence, il est souvent nécessaire de
les redéfinir, afin de gérer certaines actions particulières devant
avoir lieu lors de la création ou de la destruction d'un objet; de
fait, c'est presque une obligation dans le cas des constructeurs, et
souvent nécessaire pour le destructeur et les constructeurs
spécifiques (typiquement lorsque l'objet doit mobiliser une ressource
non duplicable, tel que la mémoire, un périphérique, un fichier,
etc.)
Déclaration
Pour que le compilateur puisse identifier les constructeurs et
destructeurs, ces derniers doivent être prototypés différemment que
les autres méthodes :
Constructeur(s) |
- Aucune indication de type de retour (pas même void)
- Identificateur identique à celui de la classe
|
Destructeur |
- Aucune indication de type de retour (pas même void)
- Identificateur identique à celui de la classe, précédé du signe «~» (tilde)
- Liste d'argument vide
|
Constructeur de copie
Il existe un constructeur, appelé constructeur de copie, qui joue un rôle
particulier: c'est le constructeur utilisé lorsque l'on cherche à obtenir une nouvelle
instance, copie d'une autre instance déjà initialisée. Ce constructeur est important,
car c'est celui qu'utilise le compilateur lorsqu'il doit effectuer de telles copies
(par exemple lors du passage par valeur d'une instance à une fonction ou une
méthode)
Le prototype du constructeur de copie est figé: le constructeur doit admettre un et
un seul argument, qui est l'instance à dupliquer, passée par référence.
Si ce constructeur n'est pas explicitement défini par le programmeur, le compilateur
se chargera d'en fabriquer un, réalisant une copie membre à membre des attributs.
Invocation des constructeurs et destructeurs
L'invocation des constructeurs est semi-explicite, en ce sens que, dans la plupart
des cas, le programmeur choisi le moment et quel constructeur il faut invoquer,
mais l'invocation des destructeurs est [presque] toujours implicite. En d'autre
terme, le programmeur connaît le contexte dans lequel un objet est créé,
mais ne peut pas connaître le contexte dans lequel l'objet est détruit.
Exemple
class Rectangle
{
public:
int hauteur, largeur; // deux attributs publics
Rectangle(); // le constructeur par défaut
Rectangle(int); // un constructeur
Rectangle(int,int); // un autre constructeur
Rectangle(const Rectangle&); // le constructeur de copie
~Rectangle(); // le destructeur
// ... des méthodes ...
};
/* Définition des méthodes */
Rectangle::Rectangle() // cstr par défaut
: hauteur(0), // section d'initialisation des attributs
largeur(0)
{ }
Rectangle::Rectangle(int d) // cstr quelconque
: hauteur(d),
largeur(d)
{ }
Rectangle::Rectangle(int h, int l) // cstr quelconque
: hauteur(h),
largeur(l)
{ }
Rectangle::Rectangle(const Rectangle& r) // cstr de copie
: hauteur(r.hauteur),
largeur(r.largeur)
{ }
int main()
{
Rectangle r1; // inst. & invoc. du constructeur par défaut
Rectangle r2(18); // inst. & invoc. d'un constructeur
{ // un bloc
Rectangle r3(r1); // inst. & invoc. du constructeur de copie
...
} // -> invocation implicite du destructeur de r3 car
// sa portée est maintenant dépassée
...
} // -> invocation implicite des destructeurs de r1 et r2
La surcharge des opérateurs
Il est possible de définir des opérateurs agissant sur les
instances d'une classe, et d'utiliser ces opérateurs comme les
opérateurs mathématiques et logiques du C++ (opérateurs +, -, *, /, <,
>, ==, ...).
Pour cela, on définit, au niveau de la classe, une méthode nommée:
"operator+", "operator-", "operator*", ...
La méthode ainsi créée peut alors s'appeler par "A + B", ou
indifféremment par "A.operator+(B)".
Exemple : Pour utiliser l'opérateur * sur des objets
de classe
MaClasse, on définit dans MaClasse la méthode suivante :
MaClasse operator* (MaClasse x)
{
MaClasse valeur_de_retour;
// corps de la méthode
...
return valeur_de_retour;
}
L'opérateur peut alors être utilisé avec :
MaClasse A,B,C;
// affectation de valeurs à A et B
...
C = A * B;
Dernière mise à jour :
$Date: 2009-09-11 17:10:52 +0200 (Fri, 11 Sep 2009) $ ($Revision: 25 $)
|