OVH Cloud OVH Cloud

Polymorphisme ?

28 réponses
Avatar
PurL
Bonjour,

Je voudrais faire un truc, et d'un je sais pas comment faire et dedeux je
crois que ce que je veux faire s'appelle le polymorphisme.
Explications :

J'ai une classe parent et des classes enfants dérivés de parent.
Toutes les instances de mes classes enfants sont stockées dans une liste de
pointeurs.
Quand je veux accéder à une variable membre commune à toutes les classes
enfants par héritage de la classe parent, je caste avec le type parent :

(parent *)list(i)->ma_variable = 0;

Par contre, j'aimerais appeler une fonctions membre dont le prototype est
présent dans la classe parent et redéclarée dans toutes les classes enfants
car pour chaque classe enfant le code de cette fonction diffère. Mais je ne
peux pas faire :

(parent *)list(i)->ma_fonction();

car j'appelle celle de parent, et je ne peux pas caster avec le type enfant
correspondant car je ne sais quel pointeur de la liste va etre utilisé...

Comment faire pour que :

list(i)->ma_fonction();

appelle la fonction membre de la classe enfant désigné par le pointeur
list(i) ?

Merci,

PurL

8 réponses

1 2 3
Avatar
Seb
[ ...]

La règle que donne Herb Sutter, c'est ou bien, la classe a un
destructeur virtuel, ou bien elle a un destructeur protégé, ou bien,
tu n'en dérives pas.


Pour info, dans quel cas c'est intéressant d'avoir un destructeur protégé ?

Sébastien

Avatar
kanze
"Seb" wrote in message
news:<bpi4ek$5m0$...
[ ...]

La règle que donne Herb Sutter, c'est ou bien, la classe a un
destructeur virtuel, ou bien elle a un destructeur protégé, ou bien,
tu n'en dérives pas.


Pour info, dans quel cas c'est intéressant d'avoir un destructeur
protégé ?


Quand tu ne veux pas que les gens fassent un delete de l'objet à travers
un pointeur à la classe de base.

Un bon exemple serait une classe comme std::exception. C'est une classe
conçue pour servir de classe de base. Et pour qu'elle soit utile, il
faut que l'héritage soit publique. En revanche, elle ne contient pas de
données, et les classes dérivées sont souvent très légères aussi. Et
elle ne représente pas vraiment un concepte avec un rapport estUn --
j'imagine mal une utilisation des std::exception*. Il n'y a donc en
principe aucune raison pour imposer le coût des fonctions virtuelles
(typiquement, un pointeur de plus dans l'objet) aux classes dérivées.

Néaumoins, parce que l'héritage est publique, utile ou non,
l'utilisateur peut obtenir facilement un std::exception*. Et un delete à
travers ce pointeur, c'est un comportement indéfini. En rendant le
destructeur protégé, on l'empêche. C'est une petite protection.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
Seb
a écrit dans le message news:

"Seb" wrote in message
news:<bpi4ek$5m0$...
[ ...]

La règle que donne Herb Sutter, c'est ou bien, la classe a un
destructeur virtuel, ou bien elle a un destructeur protégé, ou bien,
tu n'en dérives pas.


Pour info, dans quel cas c'est intéressant d'avoir un destructeur
protégé ?


Quand tu ne veux pas que les gens fassent un delete de l'objet à travers
un pointeur à la classe de base.

Un bon exemple serait une classe comme std::exception. C'est une classe
conçue pour servir de classe de base. Et pour qu'elle soit utile, il
faut que l'héritage soit publique. En revanche, elle ne contient pas de
données, et les classes dérivées sont souvent très légères aussi. Et
elle ne représente pas vraiment un concepte avec un rapport estUn --
j'imagine mal une utilisation des std::exception*. Il n'y a donc en
principe aucune raison pour imposer le coût des fonctions virtuelles
(typiquement, un pointeur de plus dans l'objet) aux classes dérivées.

Néaumoins, parce que l'héritage est publique, utile ou non,
l'utilisateur peut obtenir facilement un std::exception*. Et un delete à
travers ce pointeur, c'est un comportement indéfini. En rendant le
destructeur protégé, on l'empêche. C'est une petite protection.



Perso, j'aurais pensé à faire un destructeur "purement virtuel", d'ailleurs
esce possible ? (je n'ai pas testé) et si oui, c'est quoi la différence
fondamentale ?

Sébastien.



Avatar
Jean-Marc Bourguet
"Seb" writes:

Perso, j'aurais pensé à faire un destructeur "purement virtuel", d'ailleurs
esce possible ? (je n'ai pas testé) et si oui, c'est quoi la différence
fondamentale ?


Un destructeur virtuel pur ca existe mais n'a pas l'effet souhaite.
Virtuel pur impose que les derives le definisse. (Mais n'empeche pas
la definition pour la classe, c'est meme obligatoire pour le
destructeur).

Ici on veut empeche l'appel a travers un pointeur vers la classe de
base.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Seb
"Jean-Marc Bourguet" a écrit dans le message news:

"Seb" writes:

Perso, j'aurais pensé à faire un destructeur "purement virtuel",
d'ailleurs


esce possible ? (je n'ai pas testé) et si oui, c'est quoi la différence
fondamentale ?


Un destructeur virtuel pur ca existe mais n'a pas l'effet souhaite.
Virtuel pur impose que les derives le definisse. (Mais n'empeche pas
la definition pour la classe, c'est meme obligatoire pour le
destructeur).

Ici on veut empeche l'appel a travers un pointeur vers la classe de
base.


Merci, je ne savais pas (je m'en doutais un peu).

Sébastien


Avatar
espie
In article <bpatfc$vvp$,
PurL wrote:
Quand tu écris une classe qui ne dérive de rien, une bonne règle de
base, c'est que s'il y a une fonction virtuelle, le destructeur doit
être virtuel.


Et si la classe dérivée n'a rien à detruire de plus que la classe de base,
le destructeur n'a pas besoin d'etre virtuel ?

PurL


Et comment tu sais que toutes les classes qui pourront deriver de ta classe
de base n'auront rien de plus a detruire ?


Avatar
PurL
Quand tu écris une classe qui ne dérive de rien, une bonne règle de
base, c'est que s'il y a une fonction virtuelle, le destructeur doit
être virtuel.


Et si la classe dérivée n'a rien à detruire de plus que la classe de
base, le destructeur n'a pas besoin d'etre virtuel ?


Et comment tu sais que toutes les classes qui pourront deriver de ta
classe de base n'auront rien de plus a detruire ?


Parceque c'est moi qui l'est écrit :)
Mais bon, s'il n'y aucun inconvénient à mettre virtual le destructeur et
qu'on peut dire "qui peut le plus peut le moins", alors je peut mettre
"betement" virtual le destructeur meme si j'ai pas tout saisie le pourquoi
du comment ?

PurL



Avatar
Christophe Lephay
PurL wrote:
Quand tu écris une classe qui ne dérive de rien, une bonne règle de
base, c'est que s'il y a une fonction virtuelle, le destructeur
doit être virtuel.


Et si la classe dérivée n'a rien à detruire de plus que la classe de
base, le destructeur n'a pas besoin d'etre virtuel ?


Et comment tu sais que toutes les classes qui pourront deriver de ta
classe de base n'auront rien de plus a detruire ?


Parceque c'est moi qui l'est écrit :)


Mais justement, ce n'est pas forcément toi qui écrira les classes
dérivées...

Mais bon, s'il n'y aucun inconvénient à mettre virtual le destructeur
et qu'on peut dire "qui peut le plus peut le moins",


Plutôt que parler de plus et de moins, il y a une solution qui marche et une
autre qui ne marche pas...

alors je peut
mettre "betement" virtual le destructeur meme si j'ai pas tout saisie
le pourquoi du comment ?


Si tu n'as pas tout saisi, je te conseille de relire les réponses.
Comprendre pourquoi le destructeur doit être virtuel implique comprendre ce
qu'est un destructeur et ce que sont les fonctions virtuels. Si celà semble
une La Palissade, il n'en reste pas moins que ce sont deux notions que tu as
intérêt à comprendre parfaitement :)

Chris




1 2 3