« Programmation C++/Les classes » : différence entre les versions

Contenu supprimé Contenu ajouté
m Formatage, ajout de code
Ligne 64 :
Les constructeurs et destructeur d'une classe sont des fonctions membres particulières de cette classe.
=== Constructeurs ===
* Lorsqu'on crée une nouvelle instance d'une classe, les données membres de cette instance ne sont pas initialisées par défaut. Un constructeur est une fonction membre qui sera appelée au moment de la création d'une nouvelle instance d'une classe. Il peut y avoir plusieurs constructeurs d'une classe avec différents paramètres qui serviront à initialiser notre classe. Le constructeur d'une classe A est appelé automatiquement lorsqu'on crée une instance en écrivant : ''A toto;'' ou encore ''A toto(6,9);''. Ils sont également appelés lorsqu'une instance est créée grâce à l'opérateur <ttcode>new</ttcode>.
* Parmi les constructeurs, on retrouve une série de constructeurs particuliers:
** Le '''constructeur par défaut''': c'est le constructeur sans argument. Si aucun constructeur n'est présent explicitement dans la classe, il est généré par le compilateur.
Ligne 78 :
 
=== Destructeurs ===
Les destructeurs sont appelés lorsqu'une instance d'une classe doit être détruite. Cela arrive à la fin de l'exécution d'une fonction/méthode: si vous avez déclaré, localement à une fonction/méthode, un élément d'une classe A par ''A toto;'' alors à la fin de l'exécution de la fonction/méthode, le destructeur de la classe est appelé. Il est également appelé lorsqu'on détruit une instance grâce à <ttcode>delete</ttcode>. Il ne peut y avoir qu'un seul destructeur pour une même classe. S'il n'est pas explicitement présent dans la classe, il sera généré par le compilateur. La syntaxe est identique à celle du constructeur, mais le destructeur est introduit par un tilde:
 
<code>~A();</code>
Ligne 214 :
 
== Les opérateurs new et delete ==
Il est parfois intéressant de créer dynamiquement de nouvelles instances d'une classe. Cela s'avère indispensable lorsque vous manipulez certaines structures de données complexes. L'opérateur <ttcode>new</ttcode> permet de créer une nouvelle instance d'une classe <code>A</code> en écrivant :
A* pointeur=new A; // Ou bien:
A* pointeur=new A();
Ligne 220 :
Si le constructeur de la classe A prend des arguments, la syntaxe devient:
A* pointeur=new A(''arguments'');
La variable <ttcode>pointeur</ttcode> doit alors être du type <ttcode>A*</ttcode>.
 
La libération se fait en utilisant l'opérateur <ttcode>delete</ttcode> et le destructeur de la classe est appelé:
delete pointeur;
 
Ligne 689 :
 
=== Méthodes virtuelles ===
Dans l'exemple précédent, si l'on ajoute une autre méthode à la classe <ttcode>VehiculeRoulant</ttcode> :
 
* Fichier '''VehiculeRoulant.h'''
Ligne 727 :
}
</source>
Alors si on utilise la méthode <ttcode>accelererEtAvancer()</ttcode> sur un objet de classe <ttcode>Automobile</ttcode>, le résultat sera incorrect, car la méthode <ttcode>avancer()</ttcode> appelée sera celle définie par la classe <ttcode>VehiculeRoulant</ttcode>.
 
Pour que ce soit celle de la classe <ttcode>Automobile</ttcode> qui soit appelée, il faut que la méthode <ttcode>avancer()</ttcode> soit définie comme virtuelle dans la classe de base <ttcode>VehiculeRoulant</ttcode> :
 
* Fichier '''VehiculeRoulant.h'''
Ligne 753 :
</source>
 
Le mot clé <ttcode>virtual</ttcode> indique une méthode virtuelle, c'est à dire que son adresse n'est pas fixe, mais dépend de la classe de l'objet (le compilateur construit une table interne des méthodes virtuelles pour chaque classe).
Il est possible d'accéder à une méthode précise de la table des méthodes virtuelles, en indiquant la classe de la méthode à appeler. Par exemple, pour appeler la méthode <ttcode>avancer()</ttcode> de <ttcode>VehiculeRoulant</ttcode> à partir d'une méthode de automobile:
<source lang="cpp">
void Automobile::avancer()
Ligne 780 :
Par exemple, si l'on possède une classe décrivant un véhicule roulant, et une classe décrivant un navire, on pourrait créer une classe décrivant un véhicule amphibie qui hériterait des propriétés et méthodes de véhicule roulant et de navire.
 
L'héritage multiple peut poser des problèmes de définitions multiples de méthodes virtuelles. Supposons que l'on ait une classe <ttcode>Base</ttcode> ayant les sous-classes <ttcode>H1</ttcode> et <ttcode>H2</ttcode> qui en dérivent. Si l'on crée une classe <ttcode>Finale</ttcode> héritant à la fois de <ttcode>H1</ttcode> et de <ttcode>H2</ttcode>, alors, les instanciations des objets de classe provoqueront des appels successifs des constructeurs. D'abord <ttcode>Finale::Finale()</ttcode>, puis pour ses parents <ttcode>H1::H1()</ttcode> et <ttcode>H2::H2()</ttcode>, puis, le parent de <ttcode>H1</ttcode> <ttcode>Base::Base()</ttcode>, et enfin <ttcode>Base:Base()</ttcode> pour le parent de <ttcode>H2</ttcode>. On remarque alors que le constructeur de la classe <ttcode>Base</ttcode> est appelé à toute instanciation d'un objet de classe <ttcode>Finale</ttcode>. En C++, il existe un moyen d'éviter cela et de ne faire appel au constructeur de <ttcode>Base</ttcode> qu'une seule fois. Pour cela, il suffit d'indiquer lors des héritages le mot-clé <ttcode>virtual</ttcode> pour indiquer au compilateur que les constructeurs des classes multi-héritées ne doivent être appelées qu'une seule fois.
<source lang="cpp">
class Base
Ligne 844 :
=== Syntaxe ===
<source lang="cpp"> virtual type nom_méthode(paramètres)=0;</source>
Une telle méthode définie uniquement dans une sous-classe est nécessairement virtuelle. Le mot-clé <ttcode>virtual</ttcode> est donc optionnel.
<source lang="cpp">type nom_méthode(paramètres)=0; // Méthode d'une sous classe encore abstraite