OVH Cloud OVH Cloud

Heritage

21 réponses
Avatar
Axel
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.

SI quelqu un peut m aider..
Merci d avance.

1 réponse

1 2 3
Avatar
kanze
drkm <fr.comp.lang.c++@fgeorges.org> wrote in message
news:...
Jan Rendek writes:

struct A
{
inline A::A() { this->f(); }
void f() { g(); }
virtual void g() = 0;
};

struct B : A
{
inline virtual void g() {}
};

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



1 2 3