Constructeurs et destructeur d'une classe en C++
Constructeurs d'une classe
Un constructeur est une fonction membre d'une classe qui initialise les objets d'une classe. En C ++, le constructeur est automatiquement appelé lors de la création de l'objet (instance de la classe). C'est une fonction membre spéciale de la classe.
Un constructeur aura exactement le même nom que la classe et il n’a aucun type de retour, même le type void. Les constructeurs peuvent être très utiles pour définir les valeurs initiales de certaines données membres.
Si nous ne spécifions pas de constructeur, le compilateur C ++ génère un constructeur par défaut pour nous (n'attend aucun paramètre et a un corps vide).
En C ++, il existe trois types de constructeurs :
- Constructeur par défaut
- Constructeur d'initialisation (paramétré)
- Constructeur par copie
Constructeur par défaut
Un constructeur par défaut est un constructeur qui ne prend aucun argument. Il n'a pas de paramètres.
Exemple :
#include <iostream> using namespace std; class Voiture { private: int Id; double vitesse; public: Voiture() { Id = 1; vitesse = 250.5; cout << "Je suis le constructeur par défaut" << endl; } }; int main() { Voiture v1; return 0; }
Généralement, le constructeur par défaut est utilisé pour donner des valeurs par défaut aux données membres
Constructeur d'initialisation
Il est possible de passer des arguments aux constructeurs. Généralement, ces arguments aident à initialiser un objet lors de sa création. Pour créer un constructeur paramétré, ajoutez-y simplement des paramètres.
Lorsque vous définissez le corps du constructeur, utilisez les paramètres pour initialiser l’objet.
Exemple 1:
#include <iostream> using namespace std; class Voiture { private: int Id; double vitesse; public: Voiture(int a, double b) { Id = a; vitesse = b; cout << "Je suis le constructeur paramétré " << endl; } void afficher() { cout << "Id= " << Id << " - " << " Vitesse = " << vitesse << endl; } }; int main() { Voiture v1(1, 250.5); v1.afficher(); return 0; }
Id= 1 - Vitesse = 250.5
Lorsqu'un objet est déclaré avec un constructeur paramétré, les valeurs initiales doivent être transmises en tant qu'arguments à la constructeur. La manière normale de déclarer un objet peut ne pas fonctionner. Les constructeurs peuvent être appelés explicitement ou implicitement.
Voiture v1(1, 250.5); // Appel implicite Voiture v2 = Voiture(1, 250.5); // Appel explicite
Utilisation de listes d'initialisation pour initialiser des champs
dans le cas d'un constructeur paramétré, la liste d'initialisation est utilisée pour initialiser les données membres d'une classe. La liste des membres à initialiser est indiquée avec le constructeur sous forme de liste séparée par des virgules suivie de deux points.
Exemple 2:
#include <iostream> using namespace std; class Voiture { private: int Id; double vitesse; public: Voiture(int a, double b) : Id(a), vitesse(b) { cout << "Je suis le constructeur paramétré " << endl; } void afficher() { cout << "Id= " << Id << " - " << " Vitesse = " << vitesse << endl; } }; int main() { Voiture v1(1, 250.5); Voiture v2 = Voiture(2, 140); v1.afficher(); v2.afficher(); return 0; }
Je suis le constructeur paramétré
Id= 1 - Vitesse = 250.5
Id= 2 - Vitesse = 140
Si pour une classe Test, vous devez initialiser plusieurs champs X, Y, Z, etc., vous pouvez utiliser la même syntaxe et séparer les champs par une virgule comme suit
Test(int a, int b, int c) : X(a), Y(b), Y(c){ }
Constructeur par copie
Un constructeur de copie est une fonction membre qui initialise un objet en utilisant un autre objet de la même classe.
Le constructeur de copie est utilisé pour
- Initialiser un objet par un autre du même type.
- Copiez un objet pour le transmettre en tant qu'argument à une fonction.
- Copier un objet pour le renvoyer d'une fonction.
Un constructeur de copie a le prototype de fonction générale suivant:
nomClasse (const nomClasse & autre_objet);
Exemple :
#include <iostream> using namespace std; class Voiture { private: int Id; double vitesse; public: // constructeur paramétré Voiture(int a, double b) : Id(a), vitesse(b) {} // constructeur par copie Voiture(const Voiture &v) { Id = v.Id; vitesse = v.vitesse; cout << "Je suis le constructeur par copie " << endl; } void afficher() { cout << "Id= " << Id << " - " << " Vitesse = " << vitesse << endl; } }; int main() { Voiture v1(1, 250.5); Voiture v2 = v1; v2.afficher(); return 0; }
Id= 1 - Vitesse = 250.5
Si un constructeur de copie n'est pas défini dans une classe, le compilateur lui-même en définit un. Si la classe a des variables de pointeur et des allocations de mémoire dynamiques, il est indispensable de disposer d'un constructeur de copie.
Destructeur d'une classe
Un destructeur est une fonction membre spéciale d'une classe qui est exécutée chaque fois qu'un objet de sa classe sort de la portée ou lorsque l'expression delete est appliquée à un pointeur sur l'objet de cette classe.
Un destructeur aura exactement le même nom que la classe préfixée par un tilde (~) et il ne peut ni renvoyer de valeur ni prendre de paramètres. Destructor peut être très utile pour libérer des ressources avant de sortir du programme, comme fermer des fichiers, libérer des mémoires, etc.
Exemple :
#include <iostream> using namespace std; class Voiture { private: char *marque; int Id; double vitesse; public: // constructeur paramétré Voiture(char *m, int a, double b) { int taille = strlen(m); marque = new char[taille + 1]; strcpy(marque, m); Id = a; vitesse = b; } ~Voiture() { cout << "Je suis le destructeur" << endl; delete[] marque; } void afficher() { cout << "Id = " << Id << " - " << " Vitesse = " << vitesse << " - marque = " << marque << endl; } }; int main() { Voiture v1("BMW", 1, 250.5); v1.afficher(); return 0; }
Je suis le destructeur
Si nous ne spécifions pas de destructeur dans la classe, le compilateur crée un destructeur par défaut pour nous. Le destructeur par défaut fonctionne très bien sauf si nous avons une mémoire ou un pointeur dynamiquement alloués dans la classe. Quand une classe contient un pointeur vers la mémoire allouée, nous devrions écrire un destructeur pour libérer la mémoire avant que l'instance de classe ne soit détruite. Cela doit être fait pour éviter une fuite de mémoire.