int main(int argc, char *argv[])
{
B b;
return 0;
}
Ce code ne compile pas sous gcc 3.3.3 avec une erreur du genre appel de
fonction virtuelle pure. Sous visual studio 6.0 sp6 il compile mais ne
linke pas
int main(int argc, char *argv[])
{
B b;
return 0;
}
compile linke et plante à l'exécution avec les 2 compilateurs
mentionnés, l'erreur étant du genre "pure virtual function called"
Je comprend à peu près ce qui se passe : la partie correspondant à "B"
n'est pas encore construite que le constructeur de "A" essaye d'appeller
une méthode virtuelle à laquelle il n'a pas encore accès...
mais ma question est :
que dis la norme ?, est-ce une non-conformité du compilo ? pourquoi le
compilo voit-il le problème au moment de la compilation lorsque l'appel
est direct depuis le compilateur et ne dis rien si on augmente d'un
niveau d'indirection ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Arnaud Debaene
Mathieu Peyréga wrote: <snip>
mais ma question est : que dis la norme ?, Qu'on a pas le droit d'appeler une fonction virtuelle depuis un constructeur
ou un destructeur. Ou plus précisément, on peut l'appeler mais la liaison est statique, c'est à dire que c'est la fonction définie dans la classe du constructeur/destructeur en cours qui est appelée. Si ta fonction est virtuelle pure, il n'y a bien sûr pas d'implémentation d'une telle fonction, d'où ton plantage.
est-ce une non-conformité du compilo ? Non.
pourquoi le compilo voit-il le problème au moment de la compilation lorsque l'appel est direct depuis le compilateur et ne dis rien si on augmente d'un niveau d'indirection ? Parce que le compilateur n'est pas assez malin pour suivre ton niveau
d'indirection et se rendre compte que tu appelles un méthode pure. Dans le raisonnement du compilateur, g pourrait être appelée après la construction de l'objet et est donc parfaitement valide en elle-même. Il ne vérifie pas le fait que l'appel de g depuis le constructeur est invalide. La norme ne dicte rien du tout concernant la clareté/pertinence des messages d'erreurs du compilateur ;-)
Arnaud
Mathieu Peyréga wrote:
<snip>
mais ma question est :
que dis la norme ?,
Qu'on a pas le droit d'appeler une fonction virtuelle depuis un constructeur
ou un destructeur. Ou plus précisément, on peut l'appeler mais la liaison
est statique, c'est à dire que c'est la fonction définie dans la classe du
constructeur/destructeur en cours qui est appelée. Si ta fonction est
virtuelle pure, il n'y a bien sûr pas d'implémentation d'une telle fonction,
d'où ton plantage.
est-ce une non-conformité du compilo ?
Non.
pourquoi le
compilo voit-il le problème au moment de la compilation lorsque
l'appel est direct depuis le compilateur et ne dis rien si on
augmente d'un niveau d'indirection ?
Parce que le compilateur n'est pas assez malin pour suivre ton niveau
d'indirection et se rendre compte que tu appelles un méthode pure. Dans le
raisonnement du compilateur, g pourrait être appelée après la construction
de l'objet et est donc parfaitement valide en elle-même. Il ne vérifie pas
le fait que l'appel de g depuis le constructeur est invalide.
La norme ne dicte rien du tout concernant la clareté/pertinence des messages
d'erreurs du compilateur ;-)
mais ma question est : que dis la norme ?, Qu'on a pas le droit d'appeler une fonction virtuelle depuis un constructeur
ou un destructeur. Ou plus précisément, on peut l'appeler mais la liaison est statique, c'est à dire que c'est la fonction définie dans la classe du constructeur/destructeur en cours qui est appelée. Si ta fonction est virtuelle pure, il n'y a bien sûr pas d'implémentation d'une telle fonction, d'où ton plantage.
est-ce une non-conformité du compilo ? Non.
pourquoi le compilo voit-il le problème au moment de la compilation lorsque l'appel est direct depuis le compilateur et ne dis rien si on augmente d'un niveau d'indirection ? Parce que le compilateur n'est pas assez malin pour suivre ton niveau
d'indirection et se rendre compte que tu appelles un méthode pure. Dans le raisonnement du compilateur, g pourrait être appelée après la construction de l'objet et est donc parfaitement valide en elle-même. Il ne vérifie pas le fait que l'appel de g depuis le constructeur est invalide. La norme ne dicte rien du tout concernant la clareté/pertinence des messages d'erreurs du compilateur ;-)
Arnaud
kanze
"Arnaud Debaene" wrote in message news:<407b21e2$0$494$...
Mathieu Peyréga wrote: <snip>
mais ma question est : que dis la norme ?,
Qu'on a pas le droit d'appeler une fonction virtuelle depuis un constructeur ou un destructeur. Ou plus précisément, on peut l'appeler mais la liaison est statique, c'est à dire que c'est la fonction définie dans la classe du constructeur/destructeur en cours qui est appelée. Si ta fonction est virtuelle pure, il n'y a bien sûr pas d'implémentation d'une telle fonction, d'où ton plantage.
C'est un peu plus complex que ça. La règle, c'est que l'appel dynamique (virtuell) d'un fonction ne doit jamais se résoudre à une fonction virtuelle pûre. Si c'est le cas (et ça ne peut être le cas que si la fonction est appelée dans un constructeur ou un destructeur), le programme a un comportement indéfini. Et ça, que la fonction soit définie ou non. En fait, tous les compilateurs que j'ai jamais utilisé termine le programme au moyen d'abort() (mais parfois sans autre message d'erreur) si on essaie de l'appeler.
Si la fonction est définie, en revanche, tu peux bien l'appeler si tu inhibes la résolution dynamique, au moyen de NomDeClasse::.
est-ce une non-conformité du compilo ? Non.
pourquoi le compilo voit-il le problème au moment de la compilation lorsque l'appel est direct depuis le compilateur et ne dis rien si on augmente d'un niveau d'indirection ?
Parce que le compilateur n'est pas assez malin pour suivre ton niveau d'indirection et se rendre compte que tu appelles un méthode pure.
C'est plus subtile que ça. Disons que le compilateur ne peut traiter le code comme une erreur réele que s'il peut prouver qu'il serait executer. Si la classe a trois constructeurs, par exemple, et il n'y a qu'un seul qui appel une fonction virtuelle pûre, un programme qui n'utilise jamais ce constructeur est légal. Un compilateur ne peut donc réfuser à compiler le code que s'il peut prouver que le constructeur en question sert réelement.
Dans le raisonnement du compilateur, g pourrait être appelée après la construction de l'objet et est donc parfaitement valide en elle-même. Il ne vérifie pas le fait que l'appel de g depuis le constructeur est invalide. La norme ne dicte rien du tout concernant la clareté/pertinence des messages d'erreurs du compilateur ;-)
C'est que l'analyse inter-fonctionnel est encore de l'exception dans les compilateurs. Ce qui veut dire, en fait, qu'il ne peuvent pas réfuser à compiler le code, parce qu'il faut de l'analyse inter-fonctionnel pour savoir que le constructeur en question est réelement appelé.
Évidemment, si le compilateur voir un appel flagrant d'une fonction virtuelle pûre dans un constructeur, il est libre à émettre un avertissement, même sans savoir si le constructeur sert réelement.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Arnaud Debaene" <adebaene@club-internet.fr> wrote in message
news:<407b21e2$0$494$636a15ce@news.free.fr>...
Mathieu Peyréga wrote:
<snip>
mais ma question est :
que dis la norme ?,
Qu'on a pas le droit d'appeler une fonction virtuelle depuis un
constructeur ou un destructeur. Ou plus précisément, on peut l'appeler
mais la liaison est statique, c'est à dire que c'est la fonction
définie dans la classe du constructeur/destructeur en cours qui est
appelée. Si ta fonction est virtuelle pure, il n'y a bien sûr pas
d'implémentation d'une telle fonction, d'où ton plantage.
C'est un peu plus complex que ça. La règle, c'est que l'appel dynamique
(virtuell) d'un fonction ne doit jamais se résoudre à une fonction
virtuelle pûre. Si c'est le cas (et ça ne peut être le cas que si la
fonction est appelée dans un constructeur ou un destructeur), le
programme a un comportement indéfini. Et ça, que la fonction soit
définie ou non. En fait, tous les compilateurs que j'ai jamais utilisé
termine le programme au moyen d'abort() (mais parfois sans autre message
d'erreur) si on essaie de l'appeler.
Si la fonction est définie, en revanche, tu peux bien l'appeler si tu
inhibes la résolution dynamique, au moyen de NomDeClasse::.
est-ce une non-conformité du compilo ?
Non.
pourquoi le compilo voit-il le problème au moment de la compilation
lorsque l'appel est direct depuis le compilateur et ne dis rien si on
augmente d'un niveau d'indirection ?
Parce que le compilateur n'est pas assez malin pour suivre ton niveau
d'indirection et se rendre compte que tu appelles un méthode pure.
C'est plus subtile que ça. Disons que le compilateur ne peut traiter le
code comme une erreur réele que s'il peut prouver qu'il serait executer.
Si la classe a trois constructeurs, par exemple, et il n'y a qu'un seul
qui appel une fonction virtuelle pûre, un programme qui n'utilise jamais
ce constructeur est légal. Un compilateur ne peut donc réfuser à
compiler le code que s'il peut prouver que le constructeur en question
sert réelement.
Dans le raisonnement du compilateur, g pourrait être appelée après la
construction de l'objet et est donc parfaitement valide en elle-même.
Il ne vérifie pas le fait que l'appel de g depuis le constructeur est
invalide. La norme ne dicte rien du tout concernant la
clareté/pertinence des messages d'erreurs du compilateur ;-)
C'est que l'analyse inter-fonctionnel est encore de l'exception dans les
compilateurs. Ce qui veut dire, en fait, qu'il ne peuvent pas réfuser à
compiler le code, parce qu'il faut de l'analyse inter-fonctionnel pour
savoir que le constructeur en question est réelement appelé.
Évidemment, si le compilateur voir un appel flagrant d'une fonction
virtuelle pûre dans un constructeur, il est libre à émettre un
avertissement, même sans savoir si le constructeur sert réelement.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
"Arnaud Debaene" wrote in message news:<407b21e2$0$494$...
Mathieu Peyréga wrote: <snip>
mais ma question est : que dis la norme ?,
Qu'on a pas le droit d'appeler une fonction virtuelle depuis un constructeur ou un destructeur. Ou plus précisément, on peut l'appeler mais la liaison est statique, c'est à dire que c'est la fonction définie dans la classe du constructeur/destructeur en cours qui est appelée. Si ta fonction est virtuelle pure, il n'y a bien sûr pas d'implémentation d'une telle fonction, d'où ton plantage.
C'est un peu plus complex que ça. La règle, c'est que l'appel dynamique (virtuell) d'un fonction ne doit jamais se résoudre à une fonction virtuelle pûre. Si c'est le cas (et ça ne peut être le cas que si la fonction est appelée dans un constructeur ou un destructeur), le programme a un comportement indéfini. Et ça, que la fonction soit définie ou non. En fait, tous les compilateurs que j'ai jamais utilisé termine le programme au moyen d'abort() (mais parfois sans autre message d'erreur) si on essaie de l'appeler.
Si la fonction est définie, en revanche, tu peux bien l'appeler si tu inhibes la résolution dynamique, au moyen de NomDeClasse::.
est-ce une non-conformité du compilo ? Non.
pourquoi le compilo voit-il le problème au moment de la compilation lorsque l'appel est direct depuis le compilateur et ne dis rien si on augmente d'un niveau d'indirection ?
Parce que le compilateur n'est pas assez malin pour suivre ton niveau d'indirection et se rendre compte que tu appelles un méthode pure.
C'est plus subtile que ça. Disons que le compilateur ne peut traiter le code comme une erreur réele que s'il peut prouver qu'il serait executer. Si la classe a trois constructeurs, par exemple, et il n'y a qu'un seul qui appel une fonction virtuelle pûre, un programme qui n'utilise jamais ce constructeur est légal. Un compilateur ne peut donc réfuser à compiler le code que s'il peut prouver que le constructeur en question sert réelement.
Dans le raisonnement du compilateur, g pourrait être appelée après la construction de l'objet et est donc parfaitement valide en elle-même. Il ne vérifie pas le fait que l'appel de g depuis le constructeur est invalide. La norme ne dicte rien du tout concernant la clareté/pertinence des messages d'erreurs du compilateur ;-)
C'est que l'analyse inter-fonctionnel est encore de l'exception dans les compilateurs. Ce qui veut dire, en fait, qu'il ne peuvent pas réfuser à compiler le code, parce qu'il faut de l'analyse inter-fonctionnel pour savoir que le constructeur en question est réelement appelé.
Évidemment, si le compilateur voir un appel flagrant d'une fonction virtuelle pûre dans un constructeur, il est libre à émettre un avertissement, même sans savoir si le constructeur sert réelement.
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34