IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Méthode virtuelle template


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par défaut Méthode virtuelle template
    Bonjour,
    j'ai un problème de conception, j'ai une classe de base qui gère les ressources défini comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class RessourceManagerBase { 
    public:
    	virtual ~RessourceManagerBase() { }
    	virtual void construct(nlohmann::json& json) = 0;
    };
    Puis vient cette classe template :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <typename T> class RessourceManager : public RessourceManagerBase {
    public:
    	void construct(nlohmann::json& json) { }
     
    	std::map<std::string, T*>& getList() const {
    		return _object;
    	}
     
    private:
    	std::map<std::string, T*> _object;
    };
    Afin d'être utilisé dans le code comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::map<std::string, RessourceManagerBase*> _manager;
    _manager["tile"] = new RessourceManager<Tile>();
    Jusque là aucun soucis. Le problème c'est comment est-ce que je peut récupérer les objets contenus dans _object.
    Je voulais écrire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, Tile*> t = _manager["tile"]->getList()
    Mais vu que _manager stock des string et des RessourceManagerBase* ça ne peut pas fonctionner.
    Je ne peut pas mettre ma fonction en virtuel dans la classe RessourceManagerBase puisque elle retourne un template...
    Du coup je ne sais vraiment pas comment faire, merci de votre aide.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Ta conception est bancale, pourquoi seule le dérivé pourrait retourner une liste ? Pourquoi la classe de base n'est pas le template, quelle est son utilité et sa plus-value ?

    Perso mes resources managers ressemblent toujours à ça (raw copié/collé donc y'a du bruit désolé, et c'est du code que je trimballe depuis des années que l'on peut aisément améliorer via shared_ptr et autres joyeusetés du genre apparu depuis )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    namespace BouSdK
    {
    	//!< specialize this function for each resource type needed
    	template< class T >
    	T* LoadResource(const std::string& _strName)
    	{
    		ALERT("Loader not found");
    		Log::Get().Critical("Unable to load Resource : %s : No loader defined !", _strName.c_str());
    		return NULL;
    	}
     
    	template< typename T >
    	class CResourcesManager : public CSingleton< CResourcesManager<T> >
    	{
    		struct Holder : public CRefCpt
    		{
    			T* m_pRsc;
    			Holder() : m_pRsc(NULL) {}
    			~Holder()
    			{
    				SafeDelete(m_pRsc);
    			}
    		};
    		typedef std::map<std::string, Holder*> MapRsc;
    		MapRsc m_map;
    		void ReleaseResource(typename MapRsc::iterator it)
    		{
    			it->second->DecRef();
    			if (it->second->GetRef() == 0)
    			{
    				SafeDelete(it->second);
    				m_map.erase(it);
    			}
    		}
    		public:
    			~CResourcesManager()
    			{
    				for (MapRsc::iterator it = m_map.begin(); it != m_map.end(); )
    				{
    					it->second->DecRef();
    					SafeDelete(it->second);
    					m_map.erase(it++);
    				}
    			}
    			T* GetResource(const std::string& _strName)
    			{
    				MapRsc::iterator it = m_map.find(_strName);
    				if (it != m_map.end())
    				{
    					it->second->IncRef();
    					return it->second->m_pRsc;
    				}
    				T* pTRsc = LoadResource<T>(_strName);
    				if (!pTRsc)
    					return NULL;
    				Holder* pRsc = new BOUSDK_HEAP Holder;
    				pRsc->m_pRsc = pTRsc;
    				m_map[_strName] = pRsc;
    				return pRsc->m_pRsc;
    			}
    			void ReleaseResource(T*& _pRsc)
    			{
    				if (!_pRsc)
    					return;
    				for (MapRsc::iterator it = m_map.begin(); it != m_map.end(); ++it)
    				{
    					if (it->second->m_pRsc == _pRsc)
    					{
    						_pRsc = NULL;
    						ReleaseResource(it);
    						return;
    					}
    				}
    			}
    			void ReleaseResource(const std::string& _strName)
    			{
    				MapRsc::iterator it = m_map.find(_strName);
    				if (it != m_map.end())
    				{
    					ReleaseResource(it);
    				}
    			}
    	};
    }
    Que j'utilise de cette manière
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    namespace BouSdK
    {
    	template<>
    	sf::Texture* LoadResource(const std::string& _strName)
    	{
    		sf::Texture* pSfTex = new BOUSDK_HEAP sf::Texture;
    		if (!pSfTex->loadFromFile(_strName))
    			if (!pSfTex->loadFromFile(BouSdK::Renderer::CSprite::TEXTURES_FOLDER+_strName))
    			{
    				Log::Get().Error("Unable to load Texture : %s", _strName.c_str());
    				SafeDelete(pSfTex);
    			}
    		return pSfTex;
    	}
    }
    //!< declare our resource manager for sf::Texture for faster access/usage
    typedef BouSdK::CResourcesManager<sf::Texture> CSFMLTextureManager;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par défaut
    pourquoi seule le dérivé pourrait retourner une liste
    Car si j'ai bien comprit ce que j'ai lu sur internet je ne peut pas écrire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class RessourceManagerBase { 
    public:
    	virtual ~RessourceManagerBase() { }
    	virtual void construct(nlohmann::json& json) = 0;
            // Ajout
    	virtual std::map<std::string, T*>& getList() const = 0; 
    };
    Pourquoi la classe de base n'est pas le template, quelle est son utilité et sa plus-value ?
    L'idée derrière c'est de pouvoir créer une map contenant tous les managers, peut importe le type sur lequel ils portent. Comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, RessourceManagerBase*> _manager;
    Et après l'ajout d'un manager :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _manager["tile"] = new RessourceManager<Tile>();
    C'est vraiment quelque chose d'important dans mon code.

    Encore merci de ton aide.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je pense que c'est une mauvaise idée de vouloir mettre tous les managers dans une map. Quand tu vas utiliser un manager de tiles, c'est pour gérer des tiles. C'est à dire qu'au point d'utilisation de ton manager, tu vas très certainement devoir savoir que l'objet que tu récupères est un tile. Dans ces circonstances, quel est l'intérêt de manipuler un manager de tiles comme s'il était un manager de n'importe quoi, et de le gérer dans une map qui mélange tous les types de managers de la terre.

    Dit autrement, je pense préférable au point d'utilisation d'utiliser (par exemple avec un singleton, ce genre de manager est peut-être un des rares cas où ce pattern n'est pas mauvais, mais des alternatives existent):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::map<std::string, Tile*> t = TileManager::instance()->getList()
    // Plutôt que
    std::map<std::string, Tile*> t = _manager["tile"]->getList()
    Pourrais-tu nous indiquer pourquoi tu tiens tant à cette map ?

    Si vraiment tu comptes persister dans ta voie, il te faudra utiliser des dynamic_cast à un moment ou à un autre pour récupérer l'information perdue.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2014
    Messages
    14
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyse système

    Informations forums :
    Inscription : Novembre 2014
    Messages : 14
    Par défaut
    Je tiens à cette map car elle met permet ensuite de créer un objet à partir de sont nom :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _manager[type].construct(parametres)

  6. #6
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    Alors essaye de faire cela avec un void* et de caster au moins avec la classe mère

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, void*> _manager;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Template & méthode virtuelle
    Par Neckara dans le forum C++
    Réponses: 16
    Dernier message: 05/02/2013, 10h02
  2. Réponses: 6
    Dernier message: 26/10/2010, 11h33
  3. méthodes virtuelles
    Par ep31 dans le forum C++
    Réponses: 2
    Dernier message: 09/11/2005, 17h21
  4. Comment l'appel à une méthode virtuelle....
    Par Blobette dans le forum C++
    Réponses: 7
    Dernier message: 07/12/2004, 13h55
  5. [C#] Méthode virtuelle
    Par jacma dans le forum Windows Forms
    Réponses: 4
    Dernier message: 07/11/2004, 08h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo