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

Langage C++ Discussion :

Déclaration anticipée d'une classe template


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 24
    Points : 22
    Points
    22
    Par défaut Déclaration anticipée d'une classe template
    Bonjour(soir) à tous

    Voici les données de mon problème:

    J'ai 2 fichiers : Singleton.h et MemoryManager.h

    Dans le premier, il y a une classe template Singleton, et dans le 2eme, une classe MemoryManager, qui est une classe fille de la classe Singleton

    Et mon but est de pouvoir utiliser les nouveaux opérateurs new et delete dans mon Singleton.

    Voici le code (je vise à créer une DLL) :
    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
     
    // Singleton.h
    #ifndef SINGLETON_H_INCLUDED
    #define SINGLETON_H_INCLUDED
     
    #include <iostream>
     
    #ifndef DLL_EXPORT
        #ifdef BUILD_DLL
            #define DLL_EXPORT __declspec(dllexport)
        #else
            #define DLL_EXPORT __declspec(dllimport)
        #endif
    #endif
     
    template<class Type>
    class DLL_EXPORT Singleton{
    public:
        static Type* instance();
        static void destroy();
    protected:
        Singleton();
        static Type* m_instance;
        virtual void creerInstance() = 0;
    private:
    };
     
     
    //MemoryManager.h
     
    #ifndef MEMORYMANAGER_H_INCLUDED
    #define MEMORYMANAGER_H_INCLUDED
     
    #ifndef DLL_EXPORT
        #ifdef BUILD_DLL
            #define DLL_EXPORT __declspec(dllexport)
        #else
            #define DLL_EXPORT __declspec(dllimport)
        #endif
    #endif
     
    class DLL_EXPORT MemoryManager : public Singleton<MemoryManager> {
     
    //...
    J'ai pensé à faire une déclaration anticipée de a classe Singleton, mais je n'arrive pas à faire une déclaration anticipée d'une classe template... faut-il passer par des typedef ? Ma solution est-elle vraiment bonne?

    Merci d'avance

  2. #2
    Membre expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Points : 3 344
    Points
    3 344
    Par défaut
    D'abord, tu ne peux pas exporter les symboles d'une classe template, puisqu'ils sont générés quand le code est compilé, sauf pour les fonctions statiques.

    Donc t'as mieu fait de juste faire ta classe Singleton toute template. Juste evite le probleme de l'instance unique qui dois être déclarée quelque part dans un cpp de toutes manières.


    Sinon,
    Ajouter un paramettre template a ton Singleton qui sera un Allocator, exactement comme tous les conteneurs de la bibliothèque standard, ensuite utilise l'allocateur dans l'implémentation du Singleton au lieu de new et delete.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Déjà, pour éviter d'avoir à réécrire à chaque fois tes directives préprocesseurs, tu devrais les mettre dans un fichier d'en-tête à part que tu inclurais chaque fois que nécessaire.

    Cela participe au respect du DRY (Do't Repeat Yourself ) et centralise les modifications à apporter éventuellement en un seul endroit .

    Ensuite, la déclaration anticipée ne fonctionne pas pour l'héritage, pour une raison toute simple :

    L'héritage est une relation EST-UN, ce qui signifie que l'utilisateur d'une classe dérivée peut la faire passer pour la classe mère.

    Il faut donc que le code qui manipule la classe dérivée "comme si c'était" la classe mère dispose ... de la définition de la classe mère (ait inclus de manière directe ou indirecte le fichier d'en-tête de la classe mère).

    Le moyen le plus simple pour s'assurer que c'est effectivement le cas est... d'inclure directement le fichier d'en-tête de la classe mère dans le fichier d'en-tête de la classe fille

    En plus, cela permet au compilateur de connaitre, entre autre, la taille de la classe mère qui intervient fatalement dans le calcul de la classe fille

    Je passe en vitesse sur le fait qu'il est préférable d'éviter les singleton, parce que ce sont des variables globales, et que les variables globales, c'est mal (les raisons ont été expliquées à moultes occasions, je te laisse faire une recherche sur le forum à ce sujet )

    Pour, quand même, répondre à ta question, la déclaration anticipée d'une classe template se fait exactement de la même manière que celle d'une classe normale, à ceci près qu'il faut préciser le template.

    Par exemple, si tu as une classe template proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    class MyTemplate
    {
        /* ..*/
    };
    la déclaration anticipée se fera sous la forme de
    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 MyTemplate;
     
    class MyClass
    {
     
    public:
        void foo(MyTemplate<type> /* const */ & arg) /* const;
     
    private:
        MyTemplate<type> * member_;
    };
    ou type correspond à un type existant.

    N'oublie pas d'i,clure le fichier d'en-tête de la classe template partout où tu auras besoin de connaitre le contenu de celle-ci
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Bonjour, merci d'avoir répondu aussi rapidement

    Alors :
    @Klaim : J'ai cherché un peu ce qu'étais un Allocator, j'ai trouvé de la doc mais je ne sais pas dans quelles situations ils faut les employer et surtout, comment... y aurait il un tutoriel, ou bien une ame charitable pour m'expliquer comment s'en servir ?

    @koala01 :
    Je passe en vitesse sur le fait qu'il est préférable d'éviter les singleton, parce que ce sont des variables globales, et que les variables globales, c'est mal (les raisons ont été expliquées à moultes occasions, je te laisse faire une recherche sur le forum à ce sujet )
    Corrigez moi si je me trompe, mais je ne vois pas de variable globales : Mon instance est protected et j'y accède grace a un getter, donc on est dans un cas encapsulé n'esce pas ?

    J'ai testé, et, en effet, je ne peut pas hérité avec une classe non implémentée, donc je vais continuer mes recherches sur les allocators, en espérant que ça seras la solution à mon problème

    Merci

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par jetSett Voir le message
    @koala01 :


    Corrigez moi si je me trompe, mais je ne vois pas de variable globales : Mon instance est protected et j'y accède grace a un getter, donc on est dans un cas encapsulé n'esce pas ?
    Le fait que ce soit encapsulé rend juste les choses "un peu moins mauvaises"...

    Ce qui est mal, c'est que, encapsulé ou non, tu restes avec une variable accessible depuis "n'importe où".

    D'autant plus que ton accesseur (hé oui, "getter" en anglais se dit "accesseur" en francais ) renvoie, au mieux une référence, au pire un pointeur, alors que, classiquement, les accesseurs sont des fonctions constantes, impliquant que la valeur renvoyée ne sera pas modifiée par ce qui la récupère.

    Ces deux problèmes cumulés font que tu n'a strictement aucun contrôle sur l'endroit où le singleton est utilisé, alors que, dans une conception "saine", on pourrait se rendre compte que seules "quelques classes" (essentiellement des fabriques et les classes gérant la durée de vie de tes objets) devraient avoir la connaissance et l'utilité de ton MemoryManager.

    Emmanuel Deloget () a écrit un article très intéressant sur le sujet sur son blog, et le lien a déjà été donné à maintes occasions. Je te conseille vivement d'essayer de le retrouver (je suis un peu fade, le dimanche ) afin de comprendre en profondeur ce que j'essaye d'expliquer en quelques lignes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Bien, je m'en vais le lire, je pense éditer mon message pour mettre le lien dedans Merci à vous.

    EDIT : http://blog.emmanueldeloget.com/inde...e-singletonite

    Je suis toujours à la recherche d'un tutoriel pour les allocators...

Discussions similaires

  1. Définition de méthodes pour une classe template
    Par Pragmateek dans le forum Langage
    Réponses: 13
    Dernier message: 20/12/2008, 00h46
  2. Class interne dans une classe template
    Par MatRem dans le forum Langage
    Réponses: 26
    Dernier message: 15/06/2006, 10h45
  3. Probleme avec une class template
    Par lenectar dans le forum Langage
    Réponses: 2
    Dernier message: 01/03/2006, 10h49
  4. Réponses: 4
    Dernier message: 08/11/2005, 15h10
  5. Trouver le Type d'une classe template dynamiquement ?
    Par Serge Iovleff dans le forum Langage
    Réponses: 3
    Dernier message: 23/09/2005, 16h48

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