problème d'héritage - C++ - Programmation
Marsh Posté le 05-08-2010 à 13:18:39
Renseigne-toi sur l'heritage virtuel (si B&C heritent virtuellement de A, il n'y en aura qu'un dans D).
Marsh Posté le 05-08-2010 à 13:48:34
Un Programmeur a écrit : Renseigne-toi sur l'heritage virtuel (si B&C heritent virtuellement de A, il n'y en aura qu'un dans D). |
merci!!
Marsh Posté le 06-08-2010 à 11:37:34
up
ne fait j'aurais encore une question ...
comment je fais si A, B et C prennent des paramètres en entrée ??
par exemple A(const char * buffer)
et : B(const char *buffer, int toto) C(const char *buffer, int toto)
buffer c'est la même chose pour tous.
une fois que j'initialise D, je dois initialisée deux fois ??
Code :
|
c'est comme ça ? dans ce cas je passe buffer 3 fois pour des constructeurs qui utilisent le même paramètre ...
merki par avance
Marsh Posté le 06-08-2010 à 11:40:55
Oui: le constructeur de A sera appele une fois, et les parametres seront ceux donne par le constructeur de la classe la plus derivee (D ici). C'est piegeux si A a un constructeur par defaut mais qu'il ne faut pas l'utiliser, si il n'y a pas d'appel a un constructeur de A dans la classe la plus derivee, c'est le constructeur par defaut qui sera appele.
Marsh Posté le 07-08-2010 à 14:03:12
ok merci!!
Y'a t-il un moyen d'éviter l'héritage virtuel ? je trouve ça vraiment complexe à mettre en œuvre et piegeux comme tu le dis
Que faut t'il faire dans ce genre de situation ?
Code :
|
i.e :
- C_1 dérive de B_1 qui dérive de A_1 - etc
- C_2 dérive de B_2 qui dérive de A_2 - etc
chaque classe A_1,B_1, ... a besoin d'hériter d'une classe correspondante A_2, B_2, ...
j'ai l'impression que ce genre de situation peut arriver souvent .... Par exemple :
A_1 est une voiture traban qui 'hérite' d'une classe A_2 qui implémente un moteur de base (à pédales )
B_1 est une voiture hummer qui 'hérite' d'une classe B_2 qui implémente un moteur à réaction
ne reste t-il que l'héritage virtuel et tout le hardcore qui va avec ?
merci par avance ...
Marsh Posté le 07-08-2010 à 20:22:21
J'ai tendance à penser que l'héritage virtuel, ca arrive plutôt rarement. Regarde si tu ne peux pas découper ton objet en des entités plus simples, essaye de séparer en terme de responsabilités. Est-ce que ta voiture doit nécessairement savoir exactement quel type de moteur elle embarque ? Ou est-ce qu'au contraire, il lui suffit d'avoir une interface basique sur comment l'utiliser et ne pas se soucier de son type exact ?
Marsh Posté le 07-08-2010 à 21:57:59
Une voiture qui hérite (virtuellement ou non) d'un moteur, ça m'inquiète.
L'héritage virtuel arrive naturellement pour les classes qui ont la fonction des interfaces de Java.
Marsh Posté le 08-08-2010 à 12:58:59
Un Programmeur a écrit : Une voiture qui hérite (virtuellement ou non) d'un moteur, ça m'inquiète. |
hello
oui l'exemple est peut être mal choisi, mais c'était pour illustrer.
mon probleme est que ma classe A_1 de base hérite d'un encodeur, qui permet d'encoder certaines données de base (type entier, flottant, etc)
ma classe B_1, qui hérite de A_1, aurait besoin d'un encodeur un peu plus sophistiqué, qui pemet d'encoder des données plus haut niveau. Donc mon encodeur sophistiqué est un type d'encodeur qui a quelques fonctions en plus (encoder un prix, un produit, etc)
Si je fais de l'agregation ou de la composition pour moi ça reviens au même: on a toujours duplication des données, ou alors je suis obligé de faire un static_cast dans ma classe B_1 mais là je perds l'intéret de l'héritage :
Code :
|
C'est peut être mieux au niveau de la sémantique, ok, mais bon ..
Du coup je ne vois pas du tout comment découper autrement La seule solution 'mauvaise' que je trouve, c'est de faire un encodeur énorme avec tout dedans, et chaque classe est responsable de ce qu'elle fait avec. Je vois pas d'autre option...
Marsh Posté le 09-08-2010 à 15:49:47
Tu peux regarder du coté du design pattern "decorator", c'est une solution pour éviter l'héritage multiple.
Marsh Posté le 09-08-2010 à 23:44:50
Paulp a écrit : Tu peux regarder du coté du design pattern "decorator", c'est une solution pour éviter l'héritage multiple. |
hello,
merci! mais je ne crois pas que ce soit adapté pour ce que je veux faire.
En fait, je crois que j'ai trouvé, il faut que j'utilise la covariance des types de retour avec des pointeurs dans mes classes. Du style :
mon problème :
Code :
|
et on veut pas utiliser l'héritage virtuel car c'est trop ba-caca-pas-beau-et-un-calvaire.
La solution, s'il en fut :
Code :
|
comme ça chaque classe a son encodeur, et chaque encodeur de ouf dérive d'un encodeur plus basique.
c'est bon ça, non ?
Marsh Posté le 10-08-2010 à 00:29:59
Pourquoi tu n'as pas de hierarchie entre les encodeurs ?
Code :
|
Ensuite tu ajoutes un membre dans A_1 pointant vers un objet EncodeurBasique que tu initialise avec le bon encodeur suivant si tu es A, B, ... (ou alors tu le passes en parametre)
Tu peux aussi definir une classe abstraite pure pour definir "l'interface" des encodeurs si tu ne souhaites pas avoir de hierarchie entre tes differents encodeurs (par exemple parce qu'il n'ont rien a voir dans leur fonctionnement interne).
Marsh Posté le 10-08-2010 à 10:13:48
in_your_phion a écrit :
|
Tes fonctions doivent avoir le même type de retour (donc ici, ton EncodeurBasique) et il faut que ton interface soit tout de même similaire entre tes deux encodeurs. Au sein de ta classe B_1, tu pourras peut-être supposer que ton encodeur est du type EncodeurComplexe ou je ne sais quoi et faire un static_cast pour accéder à ses méthodes spécifiques
Marsh Posté le 10-08-2010 à 15:04:43
hello,
mr simon a écrit : Pourquoi tu n'as pas de hierarchie entre les encodeurs ? |
je ne suis pas sur de comprendre ? Normalement si car mon encodeur complexe dérive de mon encodeur basique
theshockwave a écrit : |
Apparement non, je ne suis pas obligé de faire de static_cast si j'utilise les types de retour covariant ... :
http://www.lwithers.me.uk/articles/covariant.html
Marsh Posté le 12-08-2010 à 09:58:34
bonjour,
j'aurais encore une question s'il vous plait
Est ce que je peux faire ça ?
Code :
|
est ce que ce n'est pas trop "crade" ? car pour la classe B j'initialise B::e mais du coup B hérite de A::e (en privé donc inaccessible) qui ne sera jamais utilisé ni initialisé.
merci par avance
Marsh Posté le 12-08-2010 à 15:08:34
B n'a pas a hérité de A,mais d'une interface de A
class A : public AInterface
{
SomeType memberOfA;
};
classBA : public AInterface
{
SomeOtherType memberOfB;
}
Marsh Posté le 12-08-2010 à 17:20:55
in_your_phion a écrit : bonjour,
|
non, il n'en hérite pas en privé et A::e est toujours accessible en faisant ca :
Code :
|
Qui plus est, tu n'aurais pas de moyen d'accéder au bon e depuis les fonctions que tu pourrais vouloir factoriser dans A
Marsh Posté le 12-08-2010 à 21:10:21
theshockwave a écrit : Qui plus est, tu n'aurais pas de moyen d'accéder au bon e depuis les fonctions que tu pourrais vouloir factoriser dans A |
hello
dans ce cas je ne vois pas la solution, comment faire ?
En fait, pp à l'interface: comment, quand on a une classe :
Code :
|
pourquoi on peut faire :
Code :
|
alors que 'e' ne pointe vers aucun objet de type E alloué ???
je ne pige plus ... il me semblait que pour faire ça il faut avoir un objet alloué. Par exemple :
Code :
|
Marsh Posté le 13-08-2010 à 19:09:42
in_your_phion a écrit :
|
Ceci ne marche pas puisque "e" n'est pas statique et ce n'est ce qu'a ecris theshockwave:
Code :
|
Marsh Posté le 16-08-2010 à 17:59:08
mr simon a écrit : Ceci ne marche pas puisque "e" n'est pas statique et ce n'est ce qu'a ecris theshockwave:
|
effectivement, ça me parait bizarre que ça marche. En plus de toute manière la fonction est privée donc ce n'est pas possible même si 'e' est statique, non ?
Est ce que quelqu'un pourrait m'indiquer la solution ? je ne vois pas ... i.e. comment faire de la composition ou de l'agrégation en évitant les static_cast partout, es-ce possible ?
merci
Marsh Posté le 16-08-2010 à 18:04:51
Code :
|
tout le code générique (factorisable) doit être dans iEncoderUser, qui ne peut donc pas supposer que l'encodeur est d'un type ou d'un autre (donc pas de static cast).
A et B connaissent directement le type de leur encodeur, donc pas de cast non plus
Marsh Posté le 16-08-2010 à 18:50:46
salut,
merci beaucoup pour ta réponse ...
seulement, dans mon problème B dérive obligatoirement de A du coup je suis obligé d'utiliser l'héritage virtuel non ?
Marsh Posté le 16-08-2010 à 19:01:28
ReplyMarsh Posté le 16-08-2010 à 22:53:51
theshockwave a écrit : pourquoi l'interface commune ne te suffirait pas ? |
salut,
en fait IEncoder est une interface pour les encodeurs, et IEncodeurUser une interface pour A et B, c'est ça ?
dans ton exemple, B n'hérite plus de A ... mais les deux A et B héritent d'une interface commune iEncoderUser. Dans mon cas B est "une sorte de" A.
La seule solution que je vois, ce serait effectivement de casser l'héritage et de dire que A et B sont disctincts et héritent chacun d'un encodeur différent. Mais bon, normalement B est un bien une sorte de A
ou alors, de faire des fonctions vides dans comme dans ton interface IEncoder, mais c'est pas terrible non ? Comme ça alors ?
Code :
|
..
Marsh Posté le 17-08-2010 à 10:38:54
instancier dans ton getter me semble être une grosse erreur.
Si tu as ta classe A et que tu peux la modifier, alors tu peux la transformer en simple interface, tu dois bien pouvoir choisir qui est instancié, non ? Je soupçonne que cette contrainte que tu mets n'en est pas vraiment une. Quoiqu'il arrive, tu ne pourras pas faire quelque chose de propre si tu veux avoir B qui dérive de A.
Marsh Posté le 17-08-2010 à 13:24:07
salut
oui c'est clair
finalement j'ai changé, effectivement je pourrais pas faire quelque chose de propre avec B qui dérive de A et EncodeurComplexe qui dérive de Encodeur.
J'ai finalement un seul encodeur qui fait les trucs vraiment de base (encodage int/string, etc), et j'ai transféré les encodages plus complexes dans les classes A et B, car les traitements sont davantage fonctionnels : il appartient donc aux classes de savoir ce qu'elles encodent, pas à l'encodeur.
Donc voilà, je ne sais pas si c'est la meilleur solution, mais bon, ça me simplifie les choses...
merci encore pour ton aide!
Marsh Posté le 05-08-2010 à 12:31:16
bonjour,
j'ai une problème en fait:
- j'ai deux classes A B
- B hérite de A
- une classe C qui hérite de A
- une classe D qui hérite de C
schématiquement:
A <--- B
|
|
C <--- D
Or, je voudrais faire hériter D de B, soit :
A <--- B
| |
| |
C <--- D
le problème, c'est que D hérite de C qui contient donc A, et comme B contient A, ben si D hérite de B il contient potentiellement A deux fois...
comment faire ??
merci par avance!