En plus le cas standard d'appeler une fonction virtuelle du constructeur ou destructeur d'un objet avec des fonctions virtuelles pures vous pouvez également obtenir un appel de fonction virtuelle pure (sur MSVC au moins) si vous appelez un virtuel fonction après que l'objet a été détruit. Évidemment, c'est une très mauvaise chose à faire, mais si vous travaillez avec des classes abstraites en tant qu'interfaces et que vous vous trompez, c'est quelque chose que vous pourriez voir. C'est probablement plus probable si vous utilisez des interfaces comptées référencées et si vous avez un bug de décompte de référence ou si vous avez une condition de course de destruction d'objet/objet dans un programme multithread ... La chose à propos de ces types de purecall est qu'il est souvent moins facile de comprendre ce qui se passe comme un chèque pour les «suspects habituels» des appels virtuels dans ctor et dtor sera propre.
Pour faciliter le débogage de ces types de problèmes, vous pouvez, dans différentes versions de MSVC, remplacer le gestionnaire purecall de la bibliothèque d'exécution. Vous le faites en fournissant votre propre fonction avec cette signature:
int __cdecl _purecall(void)
et de le lier avant de lier la bibliothèque d'exécution. Cela vous donne le contrôle de ce qui se passe quand un purecall est détecté. Une fois que vous avez le contrôle, vous pouvez faire quelque chose de plus utile que le gestionnaire standard. J'ai un gestionnaire qui peut fournir une trace de pile de l'endroit où le purecall est arrivé; voir ici: http://www.lenholgate.com/blog/2006/01/purecall.html pour plus de détails.
(Notez que vous pouvez également appeler _set_purecall_handler() pour installer votre gestionnaire dans certaines versions de MSVC).
Une raison pour laquelle le compilateur n'a pas pu attraper cela, en général? – Thomas
Je ne vois aucune raison technique pour laquelle le compilateur n'a pas pu l'attraper. –
GCC me donne un avertissement seulement: test.cpp: Dans le constructeur 'Base :: Base()': test.cpp: 4: avertissement: virtuel virtuel 'base vide :: doIt()' appelé du constructeur Mais il échoue au moment de la liaison. – Thomas