Bonjour à tous :D
Est ce qu'une classe peut etre amie d'une classe abstraite?
Version imprimable
Bonjour à tous :D
Est ce qu'une classe peut etre amie d'une classe abstraite?
Il me semble oui. Je vois pas pourquoi ça ne serait pas bon.
Cependant l'intérêt en serait limité.
Ca gâche le polymorphisme. Tu peux expliquer le contexte succintement ?
J'imagine que c'est pour obtenir une classe amie de toutes les classe dérivées... ?
Bah ça ne marchera pas. Une classe A est amie de B, pas de ses filles, si je ne m'abuse.
Au temps pour moi, j'ai eu tord...
Aucun problème avec ce code...Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #include <iostream> using namespace std; class C; class B; class A { friend class B; int a; public: virtual void f() = 0; }; class C : public A { public: void f() { } }; class B { C inst; public: void f(int n) { inst.a = n; cout << inst.a << endl; } }; int main() { B b; b.f(1); return 0; }
Et bien en fait j'ai plusieurs classe manager : CSpriteManager qui affiche les sprite, CCameraManager qui gère les différentes caméra, CTextureManager pour les textures, et toutes ces classes ont une méthodes Render(laFenetreCible) : ces manager héritent tous de IManagerRenderer qui possède une méthode virtuelle pure Render(laFenetreCible).
Cependant ce n'est pas à l'utilisateur d'appeller chacune de ces méthodes, parce si j'ai 10 manager comme ceux la ça devient vite fastidieux donc j'ai mis ces méthodes en privées.
J'ai ensuite créé une classe CRenderer qui va se charger d'appeller les méthodes Render de tous ces managers à la place de l'utilisateur. Cette classe contient un vecteur
Puis elle contient aussi une méthode RenderToScreen(laFenetreCible)Code:
1
2 std::vector<IManagerRenderer*> m_vManager;
Mais comme vous le voyez cette méthode doit accéder aux méthodes Render de chaque manager (qui sont aussi de type IManagerRender puisqu'ils en héritent) qui sont en privées (pour ne pas que l'utilisateur y accède). Donc pour que mon CRenderer accède à ces méthodes privées, je souhaite qu'il soit ami de IManagerRender pour accéder à la méthode Render de cette classe et donc à toutes les méthodes Render de tous les managers qui héritent de IManagerRender.Code:
1
2
3
4
5
6 void CRenderer::Render(sf::RenderWindow *pWindow) { for(m_vManagerIter = m_vManager.begin(); m_vManagerIter != m_vManager.end(); ++m_vManagerIter) (*m_vManagerIter)->Render(pWindow); }
J'espère avoir était clair, mais c'est pas facile à expliquer^^
Visiblement ça ne pose aucun problème, l'amitié est préservée lors de l'héritage, mais pour ce qui est présent dans la classe mère seulement, normalement.
Oui, si on déclarait une fonction x() dans la classe C, B ne pourrait pas l'appeler.
Néanmoins, comme beaucoup d'autre je n'aime pas les classes amies. En général, je considère qu'une méthode est la pour une bonne raison et est donc utilisable à loisir, donc en public. Pour moi, les méthodes private ne sont la que pour partitionner un algo complexe ou pour interdire explicitement certaines choses (la copie par exemple).
Les seuls cas où je pourrais interdire l'utilisation de quoi que ce soit sont ceux où j'ai des classes à usage interne qui ne sont d'aucune utilité à l'utilisateur, mais dans ces cas la je les déclare généralement dans un namespace supplémentaire style "detail" ou "others".
J'ai pris l'habitude d'avoir un namespace privé pour y déclarer tout ce qui fait tourner mon code mais qui n'a pas lieu d'être accessible par l'utilisateur.
PS : je ne suis pas partisan de l'utilisation de l'amitié, non plus.
Mais ou est l'erreur?
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #ifndef __IManagerRender_h__ #define __IManagerRender_h__ #include <iostream> #include <SFML/Graphics.hpp> #include "CRenderer.h" namespace SLE { class IManagerRender { friend class CRenderer; public: IManagerRender(){} virtual ~IManagerRender(){} private: virtual void Render(sf::RenderWindow *pWindow) = 0; }; } #endif
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #ifndef __CRenderer_h__ #define __CRenderer_h__ #include <iostream> #include <vector> #include <SFML/Graphics.hpp> #include "CSingleton.h" namespace SLE { class IManagerRender; class CRenderer : public CSingleton<CRenderer> { friend class CSingleton<CRenderer>; public: //Enregistre un manager en tant que manager de rendu void RegisterManagerToRendering(IManagerRender *pManager); //Rendu de la scène void RenderScene(sf::RenderWindow *pWindow); private: CRenderer(); virtual ~CRenderer(); typedef std::vector<IManagerRender*> m_Vector; m_Vector m_vManager; //Vecteur des managers de rendu m_Vector::iterator m_vManagerIter; //Itérateur de parcours du vecteur }; } #endif
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include "CRenderer.h" using namespace SLE; CRenderer::CRenderer() {} CRenderer::~CRenderer() { m_vManager.clear(); } void CRenderer::RegisterManagerToRendering(IManagerRender *pManager) { if(pManager) m_vManager.push_back(pManager); } void CRenderer::RenderScene(sf::RenderWindow *pWindow) { for(m_vManagerIter = m_vManager.begin(); m_vManagerIter != m_vManager.end(); ++m_vManagerIter) (*m_vManagerIter)->Render(pWindow); }
Code:
1
2
3
4 1>c:\documents and settings\admin\bureau\projet sle - plateforme\sle\sle\crenderer.cpp(22) : error C2027: utilisation du type non défini 'SLE::IManagerRender' 1> c:\documents and settings\admin\bureau\projet sle - plateforme\sle\sle\crenderer.h(11) : voir la déclaration de 'SLE::IManagerRender' 1>c:\documents and settings\admin\bureau\projet sle - plateforme\sle\sle\crenderer.cpp(22) : error C2227: la partie gauche de '->Render' doit pointer vers un type class/struct/union/générique
ImageRender.h n'est jamais inclus.
Alors quand tu t'en sers dans crenderer.cpp, il se demande de quoi tu causes :aie:
Ce n'est pas ImageRender mais IManagerRender ^^ lol mais c'est pas le problème, il est bien inclus juste après la déclaration du namespace
Code:
1
2
3
4
5
6
7
8
9 namespace SLE { class IManagerRender; class CRenderer { ... }; }
Non il n'est pas inclus. Là c'est une déclaration anticipée.
Dans crenderer.cpp, tu dois inclure le fichier d'en-tête de IManagerRender.
par exemple.Code:#include "imanagerrender.h"
Oué ca marche bien Alp, merci à vous tous et vive developpez.com^^
Mais à quoi ça sert de mettre class IManagerRender alors que l'on inclus IManagerRender.h parce si j'enlève class IManagerRender mon compilateur me sort environ 300 erreurs
Tu mets
dans crenderer.hCode:class IManagerRender;
Cela signifie, en gros : "il existe une classe IManagerRender mais elle est définie soit plus loin dans ce fichier soit dans un autre fichier". Cela ne donne aucun détail sur les fonctions membres et attributs, entre autres.
Dans ton .cpp, tu as besoin de connaître les fonctions membres publiques de cette classe car tu les appelles! Il faut connaître donc leur prototype par exemple. Et ces informations, on les a lorsque l'on inclut le fichier d'en-tête de IManagerRender.
ok merci beaucoup Alp et tous les autres bien sûr ^^
Ta phrase reste assez floue et ambigue. Un petit rappel : http://cpp.developpez.com/faq/cpp/?p...RIEND_heritage