| |||||
| Dernière réponse | |
|---|---|
| Sujet : [C++ extreme ...] héritage virtuelle multiple et cast | |
| leander | C'est vrai que la solution c'est de ne pas faire d'héritage multiple. C'est la conclusion a laquelle on était arrivé vendredi soir aussi.
D'ailleurs dans Design Pattern ils déconseillent fortement l'héritage multiple et préconise plutot la composition. Enfin ça dépend des cas d'utilisations bien sur.... |
| Aperçu |
|---|
| Vue Rapide de la discussion |
|---|
| leander | C'est vrai que la solution c'est de ne pas faire d'héritage multiple. C'est la conclusion a laquelle on était arrivé vendredi soir aussi.
D'ailleurs dans Design Pattern ils déconseillent fortement l'héritage multiple et préconise plutot la composition. Enfin ça dépend des cas d'utilisations bien sur.... |
| LeGreg |
[jfdsdjhfuetppo]--Message édité par legreg--[/jfdsdjhfuetppo] |
| LeGreg |
|
| Tetragrammaton IHVH | legreg> Sauf que ta méthode plante lamentablement.
Si tu as une classe B qui dérive d'une classe A, tu ne peux pas passer par void* pour acceder à une méthode virtuelle : B* b = new B; void* ptr = (void*) b; A* a = (A*) ptr; a->MethodeVirtuelleB(); // va provoquer un superbe plantage :lol: Donc, tu tacheras de nous épargner ton humour sur les void* :sarcastic: Et concernant tes points 2 & 3 : personne n'est à l'abri d'un bug. Si on a inventé le typage, c'est bien pour la sécurité sinon, autant retourner à l'ASM, là c'est rapide :sarcastic: |
| leander | ouai ok...
tu aurais un exemples où il n'arrive pas à résoudre les problèmes ? que je vous ce qui peut poser problème ? |
| LeGreg | le dynamic_cast ne resout pas toutes les
ambiguites (en cas d'heritage multiple). et ca ne dispense pas a l'avance de prevoir les cas ou il peut planter pour cause de cast invalide. (en cas de plantage il renvoie un pointeur NULL ou il leve une exception bad_cast si c'est un cast de reference) A+ LEGREG |
| leander |
|
| LeGreg |
|
| leander | ah ouai, je viens de faire des tests, et apparement le new B, alloue 12 octets !!!!
Contre 4 octets (pour la vftable) si on enlève l'héritage virtuel. ça fait donc 8 octets de plus pour les RTTI... Va falloir que je pèse le pour et le contre. |
| verdoux | Oui ça rajoute des infos.
Mais si t'es vraiment contraint en taille, vaut mieux pas utiliser le c++, ou alors ne pas utiliser toutes les fonctionnalités du langage (c'est souvent ce qui est fait dans l'embarqué). |
| leander | d'accord merci. La réponse à ma question est donc de compiler en RTTI.
Es-ce que vous savez si augmente la place mémoire des instances des classes ou si c'est juste des infos rajouter dans le code ? Parce que j'ai vraiment besoin de surveiller la taille mémoire de mes programmes qui ont des restrictions assez importantes. je vais faire quelques tests. Merci encore Tetragrammaton IHVH Leander |
| wpk | SATANAS !!!!!!!!! |
| Tetragrammaton IHVH |
[jfdsdjhfuetppo]--Message édité par Tetragrammaton IHVH--[/jfdsdjhfuetppo] |
| LeGreg | oui mais ca impose de compiler avec les RTTI.
void* p = new D(); D* d = (D*)p; ca ne marche pas ca? A+ LEGREG |
| Tetragrammaton IHVH | C'est bien ce qui me semblait, il n'y a pas de problème avec les RTTI :
Je viens de tester ça :
[jfdsdjhfuetppo]--Message édité par Tetragrammaton IHVH--[/jfdsdjhfuetppo] |
| leander |
|
| leander | j'ai bien sur essayer le dynamic_cast. Et le compilo met une erreur qui dit d'utiliser un statique cast.
Et si je met un statique cast j'ai l'erreur que je t'ai indiqué. En fait pour mieux comprendre mon problème je vais situer le contexte. On fait un API ou l'on a des classes des doivent s'enregistrer sur le disque. Image que l'on fasse une classe Oiseau et une classe Moineau toute deux dérivant d'un objet sauvegardable sur le disque. Lorsque l'on enregistre ces classes sur le disque, on enregistre simplement un ID qui lors du chargement permet de retrouver des methodes utilisées pour créer l'objet. Et au chargement on fait A* p=CreateObjet( ID_chargerSurleDisque ); Et à un moment moment donnée on va utiliser cet objet en sachant que c'est pas un A* mais un Oiseau*. Donc on est obligé de faire un cast. A cela tu rajoutes de l'héritage multiple décrit ci-dessus et tu obtient mon problème. Leander |
| Tetragrammaton IHVH | Ah non en fait, c'est un autre probleme qui ne dépend pas de B ou de C : voila la doc MSDN
cannot convert an 'identifier1*' to an 'identifier2*'; conversion from a virtual base class is implied The conversion requires a cast from a virtual base class to a derived class, which is not allowed. The followings sample generates C2635:
|
| Tetragrammaton IHVH | Je comprends ton problème. Ca m'est arrivé une fois mais en fait je me suis aperçu qu'il n'y avait pas besoin de caster (d'où l'interet de l'héritage, n'est ce pas ?)
Je pense que le problème est dû au fait que le compilo ne sait pas s'il faut passer par B ou par C pour arriver à D. Essaie d'employer dynamic_cast<>, la programmation C++ puriste n'utilise plus les cast à l'ancienne. |
| leander | bon j'ai une question pointu sur l'héritage en C++. Je sais que ce problème est résolu par le Jave ou le c#, mais en C++ je ne vous pas comment faire.
J'ai défini une classe interface A (c'est à dire : une classe qui n'a que des fonctions virtuelles pures) et deux classes interfaces B et C, qui hérite de toutes les deux de A. on se trouve donc avec un code comme ceci : class A {}; class B : public A {}; class C : public A {}; Et quand je défini un classe D qui hérite de B et C, j'ai quelques problèmes. class D : public B, public C {}; En effet lors de l'appel du construteur de D, le constructeur de B est appeler une fois, celui de C une fois et celui de A deux fois. Jusqu'ici tout est normal. A est instancier deux fois. J'ai donc fais de l'héritage virtuelle : class A {}; class B : virtual public A {}; class C : virtual public A {}; et dans ce cas, ma classe A n'est instancié qu'une seule fois. C'est donc ce que je recherchais. Par contre, j'ai une méthode A* CreateObjet( int id ) qui me retourne des A* mais qui en fait crée des classes de type D* (ou autre mais qui hérite de A*)... Donc avant de faire de l'héritage multiple, je faisais : D* d=(D*)CreateObject( IdDelaClasseD ); Mais depuis que je suis passé en héritage virtual, le compilo ne veut plus convertir les Classes A* en D*. Dans la MSDN et sur d'autre site, j'ai lu que c'était interdit (Compiler Error C2635 sous visual). Donc, ma question c'est : pourquoi c'est interdit ???? Normalement il ne devrait pas y avoir de problème. non ? Es-ce que quelqu'un de savant pourrait m'expliquer ? Leander. |




