bonjour, je veux savoir pourquoi le destructeur"par défaut" d'un objet est une méthode virtuel??
J'ai pas bien compris la notion de fonction inline et comment l'utiliser.
Version imprimable
bonjour, je veux savoir pourquoi le destructeur"par défaut" d'un objet est une méthode virtuel??
J'ai pas bien compris la notion de fonction inline et comment l'utiliser.
Hmm allez je la tente.. en espérant pas me planter ;p
1 ) On définit le destructeur comme virtuel lorsqu'une classe est destinee à être dérivée. Cela permet durant l'exécution d'appeler le bon destructeur en fonction du type du pointeur qui a été alloue;
Si comme dans ce cas on ne definit pas le destructeur virtuel, et qu'on réalise ceci :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 class CMere { ~Mere(){} }; class CFille { int* tab; CFille() { tab = new int[20]; } ~CFille() { delete[] tab; } };
Le tableau de 20 entiers n'est pas détruit.. en effet c'est le destructeur de la classe CMere qui est appelé et qui est vide.Code:
1
2
3 Cmere* cm = new CFille; delete CFille;
En déclarant le destructeur virtuel, le "dynamic binding" veillera à ce que le destructeur correspondant au type de l'objet pointé soit appelé.
2 ) les fonctions déclarées inline sont lors de la compilation recopiée directement dans le code.
Cela permet de ne pas avoir dans le cas d'une fonction appelé très souvent de problème de performance - l'appel de fonction a un cout - tout en gardant la sécurité de l'encapsulation - à comparer aux #define en C -.
En espérant être dans le vrai et me faire comprendre :oops:
Je lis :
Vous pouvez alors deviner ce que l'instruction delete a; provoque : la destruction d'un objet de type A, donc l'appel de A::~A(), et de rien d'autre.
C'est "divination" est inexacte (pour ne pas dire entièrement fausse) : en fait c'est un comportement indéfini.
Ce qui signifie qu'il faut absolument un destructeur virtuel dans ce cas, même si les destructeur de la classe dérivée ne fait "rien de plus" que celui de la classe de base.
En effet, c'est la virtualité du destructeur
- qui dit à 'delete' d'aller chercher l'adresse réelle de l'objet (l'adresse de l'objet complet), qui peut être différente de celle passée à delete;
- c'est aussi elle qui permet de trouver le bon opérateur delete membre si la classe dérivée en déclare un autre que la classe de base.
Sans destructeur virtuel, l'adresse passée à 'operator delete' (la fonction, pas l'expression 'delete') peut être incorrecte et corrompre le free-store (free-store = tas). En pratique, ce cas va se produire en cas d'héritage multiple (ou virtuel).
La phrase "la destruction d'un objet de type A, donc l'appel de A::~A(), et de rien d'autre." me parait donc inappropriée.
Pour un objet automatique (variable locale d'une fonction) ou global, il n'y a aucun problème de destruction parce que le compilateur connait toujours le type réel de l'objet. La règle du destructeur virtuel s'applique aux appels à delete, avec un pointeur sur une classe de base de l'objet créé (type différent de celui utilisé avec 'new') :
La règle s'applique aussi aux appels explicites au destructeur :Code:
1
2 Base *bp = new Derived; delete bp; // le destructeur DOIT être virtuel
J'insiste peut-être lourdement, parce que la FAQ traite la chose trop à la légère AMA.Code:
1
2
3
4 Base *bp = new Derived; bp->~Base (); // le destructeur DOIT être virtuel // mais pourquoi voudriez-vous faire cela? // Ceci n'est PAS une incitation.