Puis-je appeler des fonctions virtuelles dans le constructeur (ou le destructeur)
Oui, c'est possible, mais attention, ça ne fait pas toujours ce qu'on pense. La règle est que le type dynamique d'une variable en cours de construction est celui du constructeur qui est en train d'être exécuté. Pour bien comprendre ce qui se passe, il faut donc revenir sur la différence entre le type statique d'une variable, et son type dynamique.
Prenons par exemple trois classes, C qui dérive de B qui dérive de A. Par exemple, dans :
A* a = new B();
La variable a possède comme type statique (son type déclaré dans le programme) A*. Par contre, son type dynamique est B*. Une fonction virtuelle est simplement une fonction dont on va chercher le code en utilisant le type dynamique de la variable, au lieu de son type statique, comme une fonction classique.
Maintenant, quand on crée un objet de type C, les choses se passent ainsi :
* On alloue assez de mémoire pour un objet de la taille de C.
* On initialise la sous partie correspondant à A de l'objet
* On appelle le corps du constructeur de A. Pendant cet appel, l'objet crée a pour type dynamique A.
* On initialise la sous partie correspondant à B de l'objet
* On appelle le corps du constructeur de B. Pendant cet appel, l'objet crée a pour type dynamique B.
* On initialise la sous partie correspondant à C de l'objet
* On appelle le corps du constructeur de C. Pendant cet appel, l'objet crée a pour type dynamique C.
Donc, dans le corps du constructeur de la classe B, un appel d'une fonction virtuelle appellera la version de la fonction définie dans la classe B (ou à défaut celle définie dans A si la fonction n'a pas été définie dans B), et non pas celle définie dans la classe C.
D'ailleurs, si la fonction est virtuelle pure dans B, ça causera quelques problèmes, puisqu'on tentera alors d'appeler une fonction qui n'existe pas. En général, le programme va planter, si on a de la chance, il affichera une message du style "Pure function called".
La problèmatique est exactement la même pour les destructeurs, mais dans l'ordre inverse.
Pourquoi cette règle ? Une fonction définie dans C a accès aux données membre de C. Or, on a vu que au moment où on exécute l'appel au corps du constructeur de B, ces dernières ne sont pas encore crées. On a donc préférer jouer la sécurité.
Partager