Bonjour
j ai un probleme "simple" que je n arrive pas a resoudre
j ai une classe Animal , avec une fonction virtuelle afficher() , 2
classes Chien et chat heritant de Animal.
J ai une classe Humain qui a comme attribut un tableau d' Animal
et j aimerais faire kkchose du genre :
Humain un_humain;
...
un_humain.ajouter_animal(Animal a)
qui ajouterai cet animal a dans le tableau, mais je ne sais pas trop
comment m y prendre, j aimerais eviter de devoir "reconstruite" un
animal (surtout qu il faudrait deviner quel animal est ce). Peut etre
avec les références, mais je n arrive pas à saisir précisément comment
faire.
int main(int argc, char *argv[]) { B b; system("PAUSE"); return 0; }
compile sans aucun warning, linke sans plus d'information, et plante sur les deux compilateurs... (pure virtual function called) Quelqu'un de savant pourrait-il nous éclairer sur ce que dit réellement la norme C++ à propos de ce problème ?
C'est un problème que j'ai déjà rencontré. Quand tu instancie B, le constructeur A() est appelé par chainage des constructeur puisque B hérite de A. Dans le constructeur A(), le type de dynamique de 'this' est const A*. A::f() sera appelé, qui appellera A::f(). Or A::f() est virtual pure son appel génère donc une exception.
Ce qui est intéressant dans son exemple est que A::f() n'est pas virtuelle mais qu'elle appelle A::g(), virtuelle pure. Apparemment, si tu regardes les articles précédents, son compilo est assez intelligent pour détecter l'appel d'une fonction virtuelle pure dans un constructeur. Mais pas l'appel dans le constructeur d'une fonction appelant une fonction virtuelle pure. Il y a une indirection supplémentaire qui lui fait s'emmêler les pinceaux.
Je ne dirais pas qu'il s'emmêle les pinceaux. Le code a un comportement indéfini. Il n'exige pas de message d'erreur. Considère, par exemple, les exemples suivants :
struct A { A() { f( 0 ) ; } A( int i ) { if ( i != 0 ) g() ; } virtual void g() = 0 ; void f( int i ) { if ( i != 0 ) g() ; } } ;
struct B : A { B() {} B( int i ) : A( i ) {}
virtual void g() {} } ;
int main() { B b1 ; B b2( 0 ) ; return 0 ; }
C'est un programme tout à fait légal, que tout compilateur C++ doit compiler et qui doit s'executer sans erreur. Sinon, c'est une erreur dans le compilateur.
Et en effet, ni g++ 3.2.2 ni VC++ 6.0 ne l'acceptent. Dans les deux cas, il s'agit d'une erreur dans le compilateur. Au moins dans la mésure où il reclame conformité à la norme -- j'imagine, au moins dans le cas de g++, que c'est un comportement exprès, fait dans le but de détecter le cas bien plus fréquent où l'utilisateur a en fait un comportement indéfini. (Je ne sais pas si les auteurs de g++ avaient pensé à un cas comme celui ci-dessus. Mais j'ai pas de mal à croire que même s'ils y avaient pensé, ils auraient pû laisser le code, parce que c'est utile de détecter l'erreur quand il y en a, tandis du code comme ci-dessus n'est vraiment pas utile du tout, sinon que pour poser des pièges au programmeur de maintenance.
-- 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
drkm <fr.comp.lang.c++@fgeorges.org> wrote in message
news:<wkk70ns82h.fsf@fgeorges.org>...
int main(int argc, char *argv[])
{
B b;
system("PAUSE");
return 0;
}
compile sans aucun warning, linke sans plus d'information, et
plante sur les deux compilateurs... (pure virtual function
called) Quelqu'un de savant pourrait-il nous éclairer sur ce que
dit réellement la norme C++ à propos de ce problème ?
C'est un problème que j'ai déjà rencontré. Quand tu instancie B, le
constructeur A() est appelé par chainage des constructeur puisque B
hérite de A. Dans le constructeur A(), le type de dynamique de
'this' est const A*. A::f() sera appelé, qui appellera A::f(). Or
A::f() est virtual pure son appel génère donc une exception.
Ce qui est intéressant dans son exemple est que A::f() n'est pas
virtuelle mais qu'elle appelle A::g(), virtuelle pure. Apparemment, si
tu regardes les articles précédents, son compilo est assez intelligent
pour détecter l'appel d'une fonction virtuelle pure dans un
constructeur. Mais pas l'appel dans le constructeur d'une fonction
appelant une fonction virtuelle pure. Il y a une indirection
supplémentaire qui lui fait s'emmêler les pinceaux.
Je ne dirais pas qu'il s'emmêle les pinceaux. Le code a un comportement
indéfini. Il n'exige pas de message d'erreur. Considère, par exemple,
les exemples suivants :
struct A
{
A() { f( 0 ) ; }
A( int i ) { if ( i != 0 ) g() ; }
virtual void g() = 0 ;
void f( int i ) {
if ( i != 0 ) g() ;
}
} ;
struct B : A
{
B() {}
B( int i ) : A( i ) {}
virtual void g() {}
} ;
int
main()
{
B b1 ;
B b2( 0 ) ;
return 0 ;
}
C'est un programme tout à fait légal, que tout compilateur C++ doit
compiler et qui doit s'executer sans erreur. Sinon, c'est une erreur
dans le compilateur.
Et en effet, ni g++ 3.2.2 ni VC++ 6.0 ne l'acceptent. Dans les deux cas,
il s'agit d'une erreur dans le compilateur. Au moins dans la mésure où
il reclame conformité à la norme -- j'imagine, au moins dans le cas de
g++, que c'est un comportement exprès, fait dans le but de détecter le
cas bien plus fréquent où l'utilisateur a en fait un comportement
indéfini. (Je ne sais pas si les auteurs de g++ avaient pensé à un cas
comme celui ci-dessus. Mais j'ai pas de mal à croire que même s'ils y
avaient pensé, ils auraient pû laisser le code, parce que c'est utile de
détecter l'erreur quand il y en a, tandis du code comme ci-dessus n'est
vraiment pas utile du tout, sinon que pour poser des pièges au
programmeur de maintenance.
--
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
int main(int argc, char *argv[]) { B b; system("PAUSE"); return 0; }
compile sans aucun warning, linke sans plus d'information, et plante sur les deux compilateurs... (pure virtual function called) Quelqu'un de savant pourrait-il nous éclairer sur ce que dit réellement la norme C++ à propos de ce problème ?
C'est un problème que j'ai déjà rencontré. Quand tu instancie B, le constructeur A() est appelé par chainage des constructeur puisque B hérite de A. Dans le constructeur A(), le type de dynamique de 'this' est const A*. A::f() sera appelé, qui appellera A::f(). Or A::f() est virtual pure son appel génère donc une exception.
Ce qui est intéressant dans son exemple est que A::f() n'est pas virtuelle mais qu'elle appelle A::g(), virtuelle pure. Apparemment, si tu regardes les articles précédents, son compilo est assez intelligent pour détecter l'appel d'une fonction virtuelle pure dans un constructeur. Mais pas l'appel dans le constructeur d'une fonction appelant une fonction virtuelle pure. Il y a une indirection supplémentaire qui lui fait s'emmêler les pinceaux.
Je ne dirais pas qu'il s'emmêle les pinceaux. Le code a un comportement indéfini. Il n'exige pas de message d'erreur. Considère, par exemple, les exemples suivants :
struct A { A() { f( 0 ) ; } A( int i ) { if ( i != 0 ) g() ; } virtual void g() = 0 ; void f( int i ) { if ( i != 0 ) g() ; } } ;
struct B : A { B() {} B( int i ) : A( i ) {}
virtual void g() {} } ;
int main() { B b1 ; B b2( 0 ) ; return 0 ; }
C'est un programme tout à fait légal, que tout compilateur C++ doit compiler et qui doit s'executer sans erreur. Sinon, c'est une erreur dans le compilateur.
Et en effet, ni g++ 3.2.2 ni VC++ 6.0 ne l'acceptent. Dans les deux cas, il s'agit d'une erreur dans le compilateur. Au moins dans la mésure où il reclame conformité à la norme -- j'imagine, au moins dans le cas de g++, que c'est un comportement exprès, fait dans le but de détecter le cas bien plus fréquent où l'utilisateur a en fait un comportement indéfini. (Je ne sais pas si les auteurs de g++ avaient pensé à un cas comme celui ci-dessus. Mais j'ai pas de mal à croire que même s'ils y avaient pensé, ils auraient pû laisser le code, parce que c'est utile de détecter l'erreur quand il y en a, tandis du code comme ci-dessus n'est vraiment pas utile du tout, sinon que pour poser des pièges au programmeur de maintenance.
-- 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