utilisation de classe friend - C++ - Programmation
Marsh Posté le 04-10-2005 à 10:58:53
Code :
|
Marsh Posté le 04-10-2005 à 12:22:48
alors déjà il manque un virtuel
TheFoo.A::igleu(); // A::igleu();
ça jamais jamais jamais jamais ! Il ne faut pas appeler depuis l'extérieur
Dérivé::Base::Fonction() car tu violes le mécanisme virtuel en passant outre Dérivé::Fonction(). C'est catastrophique.
Marsh Posté le 04-10-2005 à 12:27:49
bjone a écrit :
|
t'as pas déclaré igleu() en virtual
edit:
Marsh Posté le 04-10-2005 à 17:26:32
Taz a écrit : alors déjà il manque un virtuel |
heu pour moi, le virtual est nécessaire quand tu manipules tes instances via un pointeur sur A (sur la classe de base).
là je passe par un Foo & (ou Foo, ou const Foo &, s'en fous).
je vois pas en quoi j'ai besoin d'un virtual sur igleu(), si je veux utiliser l'igleu de la classe de base et non celui de la dérivée.
et passer outre Dérivé::Fonction(), pour utiliser Base::Fonction(), c'est ce que je veux faire, t'as un lien ou une page du strup qui dit que ce que je veux faire c'est mal ?
Marsh Posté le 04-10-2005 à 17:29:11
ou alors on est pas dans le même contexte ?
là je suis pas dans le cas où je manipules des instances de classes dérivées via un pointeur sur une classe de base (ok pour le virtual par design dans ce cas), mais je suis dans le cas où je manipule une instance de classe dérivée via elle-même, et je veux appeller une méthode de la classe de base.
(tiens d'ailleurs je me suis planté pour igla)
Marsh Posté le 04-10-2005 à 19:06:45
perdu. La virtualité fonctionne avec les pointeurs et les références. Passé par copie un Foo là où on attend un A, c'est mettre une grosse boîte dans une petite : tu perds de l'information, tu casses ton système objet.
Marsh Posté le 04-10-2005 à 19:10:10
bjone a écrit : |
c'est pas la même chose du tout ça.
Mais de puis l'extérieur faire un
Objet::BasePublique::fonction_membre();
c'est comme faire un
*((int*)&objet + 3) = 42;
Marsh Posté le 04-10-2005 à 20:37:33
bjone a écrit :
|
C'est l'exemple classique du masquage de nom.
Foo::igleu masque A::igleu (pas considéré par le lookup car le nom igleu est trouvé dans la scope de la class Foo)
pour y acceder, c'est comme tu as fait TheFoo.A::igleu()
Mais c'est moche, il vaut mieux faire participer A::igleu à la résolution de surcharge avec using A::igleu;
(le tout sans virtualité).
Marsh Posté le 04-10-2005 à 20:47:15
Ok en dérivant la classe A, j'y avait pensé aussi seulement je sais pas si je peux le faire : en fait j'écrit un wrapper pour ADO, je vais voir ca.
Et merci pour vos réponses
Marsh Posté le 04-10-2005 à 20:47:59
y a pas de masquage de nom, c'est juste une putain de bidouille pour tout foutre en l'air.
Marsh Posté le 04-10-2005 à 20:53:58
un peu qu'y a masquage de nom !
le code que l'ai cité ne fout rien en l'air en tout cas.
Marsh Posté le 04-10-2005 à 21:11:35
Code :
|
boom. Perdu.
edit: c'est n'importe quoi. Pourquoi laisser quelqu'un redéfinir un service pour ensuite le foutre en l'air et pisser sur ses contraintes et invariants ?
Marsh Posté le 04-10-2005 à 21:28:15
j'ai précisé "sans virtualité"
pour ton edit :
Quelle idée de mettre une fonction virtuelle publique aussi ...
Marsh Posté le 04-10-2005 à 22:48:20
sans virtualité c'est un non-sens objet
edit: sinon autant donner des noms différents.
Marsh Posté le 04-10-2005 à 22:59:15
mais pas un non sens en c++.
Et meme en virtuel, si tu renvoie dans ses 22 ta fonction virtuelle *publique*, tu peux empecher l'utilisateur d'appeler la fonction de la classe de base.
Marsh Posté le 04-10-2005 à 23:02:27
rien compris. C'est pas parce que le C++ te permet de tout faire que tu peux le faire. Pour moi tout ça c'est proche de l'UB.
Marsh Posté le 04-10-2005 à 23:19:37
Code :
|
Marsh Posté le 04-10-2005 à 23:40:08
Taz a écrit : edit: sinon autant donner des noms différents. |
pas forcément (je suis d'humeur taquine) :
Code :
|
Marsh Posté le 04-10-2005 à 23:56:44
Taz a écrit : joli pléonasme. |
effectivement !
j'ai édité.
réédité.
Marsh Posté le 05-10-2005 à 00:02:27
Taz a écrit : perdu. La virtualité fonctionne avec les pointeurs et les références. Passé par copie un Foo là où on attend un A, c'est mettre une grosse boîte dans une petite : tu perds de l'information, tu casses ton système objet. |
ok pour l'aspect Foo passé via un A par copie qui peut corrompre la cohérence de l'objet (suivant interdépendances entre la base et la classe dérivé, et surtout si il y a des virtuals qui vont employer des ressources perdues).
-mais- où je passe par copie un Foo là ou on attends un A dans le code que j'ai donné ?
dans le code que j'ai mis SANS virtual ( pourquoi mettre du virtual partout ? c'est pas une obligation quand tu sais ce que tu fais, tout est question de savoir a travers quelle "définition" de classe tu manipules l'objet, si tu manipules des objets dérivés via une classe de base, oui il faut du virtual pour la résolution au runtime, mais si tu manipules directement a travers une classe dérivée, tu connais explicitement quelle méthode utiliser au compile time), je vois pas ce qui serait illégal.
de plus, la question du monsieur c'est:
- la classe Foo utilise la classe A.
- la classe Foo est passé en paramètre de la classe Bar
- la classe Bar doit utiliser la classe A
désolé j'ai essayé de lui proposer une solution qui me semble légale, et je vois pas pourquoi il serait obligatoire de coller du virtual si jamais tu sais a l'avance que tu vas manipuler par la classe dérivée...
de plus le cas avec igleu() dans la dérivée et la base est pour montrer comment on peut effectivement revenir au scope de la classe de base.
Marsh Posté le 05-10-2005 à 07:08:56
++fab a écrit :
|
décidément !
Marsh Posté le 05-10-2005 à 11:55:32
ReplyMarsh Posté le 05-10-2005 à 13:44:00
Code :
|
transforme le passage par référence en passage par copie, et voilà.
J'ai pas bien compris le problème, notamment au niveau de "la classe Bar doit utiliser la classe A" alors qu'elle reçoit un Foo, et surtout que tu "veux cacher l'existence de A".
Si c'est juste au niveau de l'interface d'utilisation qui doit être commune entre A et Foo, mais que Foo doit en interne utiliser A sans que ce soit visible, l'héritage privé me semble une bonne solution.
Si Foo n'est pas un A ("la classe Foo utilise la classe A" ), l'héritage plublic ne me semble pas indiqué.
A moins que ce ne soit à A de dériver de Foo, et non l'inverse.
Marsh Posté le 05-10-2005 à 19:07:52
HelloWorld a écrit :
|
au contraire. Le comportement polymorphique va disparaitre.
Citation : J'ai pas bien compris le problème, notamment au niveau de "la classe Bar doit utiliser la classe A" alors qu'elle reçoit un Foo, et surtout que tu "veux cacher l'existence de A". |
ou alors, si c'est faisable, ne pas hériter et diminuer ainsi le couplage. Utiliser des données membres plutot que des héritages privés. Mais la description de son problème est trop flou pour pouvoir lui dire précisément fais ci, fais ça, AMHA.
Marsh Posté le 05-10-2005 à 19:13:20
Taz a écrit : tu prends pas beaucoup de risque là ... |
Oui, il n'y a qu'une seule fonction membre publique non virtuelle. Et le polymorphisme marche en dessous.
Comme ça, il n'est pas possible d'appeler la mauvaise fonction virtuelle. Ca représente quand meme un certain confort par rapport à la solution médiocrissime des fonctions virtuelles publiques.
Marsh Posté le 05-10-2005 à 19:23:13
ReplyMarsh Posté le 06-10-2005 à 10:14:13
++fab a écrit :
|
On est d'accord, ce qui permet d'appeler la mauvaise Un simple oublie fait sauter la "protection". Manquerait une fonction virtuelle pure par exemple pour empêcher cela.
Je suis aussi d'accord qu'on manque d'éléments pour répondre.
Marsh Posté le 08-10-2005 à 14:50:17
Citation : On est d'accord, ce qui permet d'appeler la mauvaise Un simple oublie fait sauter la "protection". Manquerait une fonction virtuelle pure par exemple pour empêcher cela. |
yep ! Le probleme, c'est que la classe Foo devait rester instanciable dans l'exemple ...
On se heurte aux inconvénients de faire un héritage public d'une classe concrète, et d'overrider des fonctions virtuelles.
Avec une classe FooBase de laquelle héritent publiquement Foo et LockedFoo, le probleme disparait, quitte à définir un destructeur virtuel pur dans FooBase.
Marsh Posté le 03-10-2005 à 20:54:53
Salut,
Je me retrouve dans un cas ou j'utilise une classe amie. Comme j'ai souvent lu que ca pouvait cacher une mauvaise conception, je demande à tout hasard si c'est le cas :
- la classe Foo utilise la classe A.
- la classe Foo est passé en paramètre de la classe Bar
- la classe Bar doit utiliser la classe A
Bon le plus simple serait effectivement de faire un get dans la classe Foo mais je veux cacher l'existence de A. D'où l'utilisation du friend.
Qu'en pensez-vous ?
Merci.