Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2978 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  utilisation de classe friend

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

utilisation de classe friend

n°1213933
hellbilly
free smile
Posté le 03-10-2005 à 20:54:53  profilanswer
 

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.
 

mood
Publicité
Posté le 03-10-2005 à 20:54:53  profilanswer
 

n°1214050
Taz
bisounours-codeur
Posté le 04-10-2005 à 01:22:33  profilanswer
 

je vois pas pourquoi tu mettrais un friend.

n°1214164
bjone
Insert booze to continue
Posté le 04-10-2005 à 10:58:53  profilanswer
 

Code :
  1. class A
  2. {
  3. public:
  4.      igla();
  5.      igleu();
  6. };
  7. class Foo : public A
  8. {
  9. public:
  10.    igleu();
  11. };
  12. class Bar
  13. {
  14. public:
  15.    void DoIt( Foo & );
  16. };
  17. void Bar::DoIt( Foo &TheFoo )
  18. {
  19.   TheFoo.igleu();  // Foo::igleu()
  20.   TheFoo.igla();  // A::igla();
  21.   TheFoo.A::igleu();    // A::igleu();
  22. }

Message cité 2 fois
Message édité par bjone le 04-10-2005 à 17:36:35
n°1214262
Taz
bisounours-codeur
Posté le 04-10-2005 à 12:22:48  profilanswer
 

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.

n°1214266
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 04-10-2005 à 12:27:49  profilanswer
 

bjone a écrit :

Code :
  1. class A
  2. {
  3. public:
  4.      igla();
  5.      igleu();
  6. };
  7. class Foo : public A
  8. {
  9. public:
  10.    igleu();
  11. };



t'as pas déclaré igleu() en virtual :o
 
edit: [:benou_grilled]


Message édité par Harkonnen le 04-10-2005 à 12:28:10
n°1214764
bjone
Insert booze to continue
Posté le 04-10-2005 à 17:26:32  profilanswer
 

Taz a écrit :

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.


 
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 ?

Message cité 1 fois
Message édité par bjone le 04-10-2005 à 17:31:57
n°1214772
bjone
Insert booze to continue
Posté le 04-10-2005 à 17:29:11  profilanswer
 

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)


Message édité par bjone le 04-10-2005 à 17:36:53
n°1214885
Taz
bisounours-codeur
Posté le 04-10-2005 à 19:06:45  profilanswer
 

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.

n°1214886
Taz
bisounours-codeur
Posté le 04-10-2005 à 19:10:10  profilanswer
 

bjone a écrit :


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 ?


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;

n°1214956
++fab
victime du syndrome IH
Posté le 04-10-2005 à 20:37:33  profilanswer
 

bjone a écrit :

Code :
  1. class A
  2. {
  3. public:
  4.      igla();
  5.      igleu();
  6. };
  7. class Foo : public A
  8. {
  9. public:
  10.    igleu();
  11. };
  12. class Bar
  13. {
  14. public:
  15.    void DoIt( Foo & );
  16. };
  17. void Bar::DoIt( Foo &TheFoo )
  18. {
  19.   TheFoo.igleu();  // Foo::igleu()
  20.   TheFoo.igla();  // A::igla();
  21.   TheFoo.A::igleu();    // A::igleu();
  22. }



 
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é).
 
 

mood
Publicité
Posté le 04-10-2005 à 20:37:33  profilanswer
 

n°1214965
hellbilly
free smile
Posté le 04-10-2005 à 20:47:15  profilanswer
 

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

n°1214967
Taz
bisounours-codeur
Posté le 04-10-2005 à 20:47:59  profilanswer
 

y a pas de masquage de nom, c'est juste une putain de bidouille pour tout foutre en l'air.

n°1214973
++fab
victime du syndrome IH
Posté le 04-10-2005 à 20:53:58  profilanswer
 

un peu qu'y a masquage de nom !
le code que l'ai cité ne fout rien en l'air en tout cas.

n°1214979
Taz
bisounours-codeur
Posté le 04-10-2005 à 21:11:35  profilanswer
 

Code :
  1. class Foo
  2. {
  3.   public:
  4.   virtual void do_something();
  5. };
  6. class LockedFoo : public Foo
  7. {
  8.   public:
  9.   virtual void do_something()
  10.   { Lock l; Foo::do_something(); }
  11. };
  12. void bar(Foo &f)
  13. {
  14.    f.Foo::do_something();
  15. }


 
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 ?


Message édité par Taz le 04-10-2005 à 21:12:58
n°1214984
++fab
victime du syndrome IH
Posté le 04-10-2005 à 21:28:15  profilanswer
 

j'ai précisé "sans virtualité" :)
 
pour ton edit :
Quelle idée de mettre une fonction virtuelle publique aussi ...

n°1215036
Taz
bisounours-codeur
Posté le 04-10-2005 à 22:48:20  profilanswer
 

sans virtualité c'est un non-sens objet
 
edit: sinon autant donner des noms différents.

Message cité 1 fois
Message édité par Taz le 04-10-2005 à 22:59:28
n°1215040
++fab
victime du syndrome IH
Posté le 04-10-2005 à 22:59:15  profilanswer
 

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.

n°1215043
Taz
bisounours-codeur
Posté le 04-10-2005 à 23:02:27  profilanswer
 

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.

n°1215051
++fab
victime du syndrome IH
Posté le 04-10-2005 à 23:19:37  profilanswer
 

Code :
  1. #include <iostream>
  2. struct Lock {};
  3. class Foo
  4. {
  5. public:
  6.     void do_something() const
  7. { do_something_core(); }
  8.     virtual ~Foo() {}
  9. protected:
  10.     virtual void do_something_core() const
  11. { std::cout << "Foo::do_something_core()\n"; }
  12. };
  13.  
  14. class LockedFoo : public Foo
  15. {
  16. private:
  17.     virtual void do_something_core() const
  18. { Lock l; Foo::do_something(); std::cout << "LockedFoo::do_something()\n"; }
  19. };
  20.  
  21. void bar(Foo &f)
  22. {
  23.     f.Foo::do_something(); // essaye d'appeler la mauvaise ...
  24. }
  25. int main()
  26. {
  27.     Foo foo;
  28.     bar(foo);
  29. }

Message cité 1 fois
Message édité par ++fab le 05-10-2005 à 00:13:54
n°1215059
Taz
bisounours-codeur
Posté le 04-10-2005 à 23:35:41  profilanswer
 

joli pléonasme.

n°1215060
++fab
victime du syndrome IH
Posté le 04-10-2005 à 23:40:08  profilanswer
 

Taz a écrit :

edit: sinon autant donner des noms différents.


 
pas forcément (je suis d'humeur taquine) :
 

Code :
  1. class B
  2. {
  3. protected:
  4.     ~B() {}
  5. public:
  6.     void foo( double ) const {}
  7. };
  8. struct D : public B
  9. {
  10.     using B::foo;
  11. private:
  12.     void foo( int ) const; // int interdit
  13. };
  14. int main()
  15. {
  16.     D d;
  17.     d.foo(4);
  18. }


Message édité par ++fab le 05-10-2005 à 00:10:23
n°1215073
++fab
victime du syndrome IH
Posté le 04-10-2005 à 23:56:44  profilanswer
 

Taz a écrit :

joli pléonasme.


effectivement !
j'ai édité.
réédité.


Message édité par ++fab le 05-10-2005 à 00:14:18
n°1215081
bjone
Insert booze to continue
Posté le 05-10-2005 à 00:02:27  profilanswer
 

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.


Message édité par bjone le 05-10-2005 à 00:04:23
n°1215147
++fab
victime du syndrome IH
Posté le 05-10-2005 à 07:08:56  profilanswer
 

++fab a écrit :

Code :
  1. #include <iostream>
  2. struct Lock {};
  3. class Foo
  4. {
  5. public:
  6.     void do_something() const
  7. { do_something_core(); }
  8.     virtual ~Foo() {}
  9. protected:
  10.     virtual void do_something_core() const
  11. { std::cout << "Foo::do_something_core()\n"; }
  12. };
  13.  
  14. class LockedFoo : public Foo
  15. {
  16. private:
  17.     virtual void do_something_core() const
  18. { Lock l; Foo::do_something_core(); std::cout << "LockedFoo::do_something_core()\n"; }
  19. };
  20.  
  21. void bar(Foo &f)
  22. {
  23.     f.Foo::do_something(); // essaye d'appeler la mauvaise ...
  24. }
  25. int main()
  26. {
  27.     Foo foo;
  28.     bar(foo);
  29.     LockedFoo foo2;
  30.     bar(foo2);
  31. }



 
décidément !


Message édité par ++fab le 05-10-2005 à 07:11:03
n°1215319
Taz
bisounours-codeur
Posté le 05-10-2005 à 11:55:32  profilanswer
 

tu prends pas beaucoup de risque là ...

n°1215462
HelloWorld
Salut tout le monde!
Posté le 05-10-2005 à 13:44:00  profilanswer
 

Code :
  1. void bar(Foo &f)
  2. {
  3.     f.Foo::do_something(); // essaye d'appeler la mauvaise ...  
  4. }


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.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°1215849
++fab
victime du syndrome IH
Posté le 05-10-2005 à 19:07:52  profilanswer
 

HelloWorld a écrit :

Code :
  1. void bar(Foo &f)
  2. {
  3.     f.Foo::do_something(); //  ( ou  f.do_something() quoi )
  4. }


transforme le passage par référence en passage par copie, et voilà.


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


 
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.

n°1215857
++fab
victime du syndrome IH
Posté le 05-10-2005 à 19:13:20  profilanswer
 

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.

n°1215876
Taz
bisounours-codeur
Posté le 05-10-2005 à 19:20:12  profilanswer
 

mais bien sur ..

n°1215881
++fab
victime du syndrome IH
Posté le 05-10-2005 à 19:23:13  profilanswer
 

Taz a écrit :

mais bien sur ..


 
... que t'es aux fraises sur ce coup.

n°1216212
HelloWorld
Salut tout le monde!
Posté le 06-10-2005 à 10:14:13  profilanswer
 

++fab a écrit :


HelloWorld a écrit :

Code :
  1. void bar(Foo &f)
  2. {
  3.     f.do_something(); // essaye d'appeler la mauvaise ...   
  4. }


transforme le passage par référence en passage par copie, et voilà.


 
au contraire. Le comportement polymorphique va disparaitre.


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.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°1218303
++fab
victime du syndrome IH
Posté le 08-10-2005 à 14:50:17  profilanswer
 

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.

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  utilisation de classe friend

 

Sujets relatifs
[résolu] Faire cohabiter une ID et un classe dans la même balise ???[AWK] Utilisation de "-v" pour passer un Array ?
Pb d association une classe a nune boite de dialog[Php][Classe][Debutant] hum, où est l'erreur dans ma classe?
Lenteur/blocage suite a l'utilisation de modules CPAN[J2ME] utilisation de bluetooth
Utilisation test[C] Utilisation mpatrol
Utilisation d'une variable en Flash depuis PHPutilisation de ToolTiptext ??
Plus de sujets relatifs à : utilisation de classe friend


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR