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.

10 réponses

1 2 3
Avatar
Loïc Joly
Twxs wrote:

Franck Branjonneau wrote:

Twxs écrivait:


il me semble que je ne me trompe pas en disant que les methode
virtuelles ne fonctionne que sur les pointeurs (j'espere ne pas dire
de betise sous peine de me faire lincher ;-) )




Prépare la corde ;-) Il y a aussi liaison dynamique avec les références.



la corde est autour de mon cou ;-)
en effet ca fonctionne et je suis sur le cul. enfin la chose qui me
rassure c'est que ca ne fonctionne pas si la classe de base est pure
virtuel.


Et bien, désolé de te dire, tu vas devoir sauter de ton tabouret une
fois que tu auras bien vérifié la corde autour de ton cou...

struct A // classe abstraite
{
virtual void f() = 0;
virtual ~A() {};
};

struct B : A
{
virtual void f() {cout << "B" << endl;};
}

void f(A &a)
{
a.f();
}

int main()
{
B b;
f(b); // Marche et affiche B
}


--
Loïc



Avatar
Twxs
Loïc Joly wrote:
Twxs wrote:

Franck Branjonneau wrote:

Twxs écrivait:


il me semble que je ne me trompe pas en disant que les methode
virtuelles ne fonctionne que sur les pointeurs (j'espere ne pas dire
de betise sous peine de me faire lincher ;-) )





Prépare la corde ;-) Il y a aussi liaison dynamique avec les références.




la corde est autour de mon cou ;-)
en effet ca fonctionne et je suis sur le cul. enfin la chose qui me
rassure c'est que ca ne fonctionne pas si la classe de base est pure
virtuel.



Et bien, désolé de te dire, tu vas devoir sauter de ton tabouret une
fois que tu auras bien vérifié la corde autour de ton cou...



j'avais mal attaché la corde, et je suis encore la ;-)
je confirme, je sais pas ce qu'a foutu mon compilateur, mais ca
compilait pas en pure virtuel (surement de ma faute).

sinon pour continuer a apprendre, c'est souvent utilisé? parceque je
fait du C++ depuis un bon moment, et j'avoue n'avoir jamais vu ca...
ca fonctionne tjs, pas de risque d'appeler a l'execution un methode
reelement virtuelle pure ?

si je me plante encore n'hesité pas, je commence a avoir l'habitude ;-)

Twxs




Avatar
kanze
Twxs wrote in message
news:<407070ab$0$31089$...
Loïc Joly wrote:
Twxs wrote:

Franck Branjonneau wrote:

Twxs écrivait:

il me semble que je ne me trompe pas en disant que les methode
virtuelles ne fonctionne que sur les pointeurs (j'espere ne pas
dire de betise sous peine de me faire lincher ;-) )


Prépare la corde ;-) Il y a aussi liaison dynamique avec les
références.


la corde est autour de mon cou ;-)
en effet ca fonctionne et je suis sur le cul. enfin la chose qui me
rassure c'est que ca ne fonctionne pas si la classe de base est pure
virtuel.


Et bien, désolé de te dire, tu vas devoir sauter de ton tabouret une
fois que tu auras bien vérifié la corde autour de ton cou...


j'avais mal attaché la corde, et je suis encore la ;-) je confirme, je
sais pas ce qu'a foutu mon compilateur, mais ca compilait pas en pure
virtuel (surement de ma faute).

sinon pour continuer a apprendre, c'est souvent utilisé?


C'est plutôt courant, oui.

parceque je
fait du C++ depuis un bon moment, et j'avoue n'avoir jamais vu ca...
ca fonctionne tjs, pas de risque d'appeler a l'execution un methode
reelement virtuelle pure ?


On ne peut pas construire un objet d'un type abstrait (c-à-d d'un type
qui a des fonctions virtuelle pûre). La risque est donc limitée.

--
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





Avatar
Twxs
wrote:

ca fonctionne tjs, pas de risque d'appeler a l'execution un methode
reelement virtuelle pure ?



On ne peut pas construire un objet d'un type abstrait (c-à-d d'un type
qui a des fonctions virtuelle pûre). La risque est donc limitée.

--


je dit ca parceque je me suis deja retrouvé face a des "pure virtual
call" a l'execution (faudrait que je retrouve l'exemple), ca arrive si
l'on joue trop avec les cast, enfin je tente de trouver sur mon disque
l'exemple histoire d'appuyer mes propos.


Avatar
Loïc Joly
Twxs wrote:
je dit ca parceque je me suis deja retrouvé face a des "pure virtual
call" a l'execution (faudrait que je retrouve l'exemple), ca arrive si
l'on joue trop avec les cast, enfin je tente de trouver sur mon disque
l'exemple histoire d'appuyer mes propos.


J'ai eu ça sous gcc dans le cas suivants :

struct A
{
A::A() {f();}
virtual void f() = 0;
};

struct B : A
{
virtual void f() {}
};

Mais ce code est effectivement non correct.

--
Loïc

Avatar
Mathieu Peyréga
Bonjour,

Le code que tu as proposé ne comple pas sous gcc 3.3.3 et ne linke pas
sous visual C++ 6.0 service pack 6
En revanche :

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 ?

Cordialement,

Mathieu


Loïc Joly a écrit:
Twxs wrote:

je dit ca parceque je me suis deja retrouvé face a des "pure virtual
call" a l'execution (faudrait que je retrouve l'exemple), ca arrive si
l'on joue trop avec les cast, enfin je tente de trouver sur mon disque
l'exemple histoire d'appuyer mes propos.



J'ai eu ça sous gcc dans le cas suivants :

struct A
{
A::A() {f();}
virtual void f() = 0;
};

struct B : A
{
virtual void f() {}
};

Mais ce code est effectivement non correct.




Avatar
Jan Rendek
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.

Avatar
drkm
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.

--drkm


Avatar
kanze
Mathieu Peyréga wrote in message
news:...

Le code que tu as proposé ne comple pas sous gcc 3.3.3 et ne linke pas
sous visual C++ 6.0 service pack 6


Le code qu'il a proposé avait un comportement indéfini. Je crois donc
qu'un compilateur est libre de le rejeter, au moins dans le cas où il
peut prover que la fonction (le constructeur) serait appelée.

En revanche :

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 ?


Que la résolution dynamique d'une fonction ne peut pas trouver une
fonction virtuelle pûre, et que le type dynamique d'un objet lors de sa
construction est le type du constructeur en train de s'exécuter. Et que
d'appeler une fonction virtuelle dans un contexte où sa résolution
donnerait une fonction virtuelle pûre est un comportement indéfini.

Le code est illégal, et a un comportement indéfini. La plupart des
compilateurs génèrent effectivement une erreur lors de l'execution.

--
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

Avatar
kanze
Jan Rendek wrote in message
news:<c56hts$e96$...

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*.


Le type de « this » dans un constructeur n'est jamais const. C'est A*.

Aussi (mais c'est un détail), le type de this dans une fonction member
d'A serait toujours A*. C'est le type de *this dont le type dynamique
peut varier, non le type de this même.

--
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