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 :

[POO] Accéder à une méthode statique à partir d'une instance


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2006
    Messages : 59
    Par défaut [POO] Accéder à une méthode statique à partir d'une instance
    |Edit:
    |Le titre du post pourrait plutôt être "Quand utiliser le Singleton ?" à
    |partir du post #5.

    Bonjour à tous ;-)

    Voici mon problème: j'ai une variable _vDrawer qui a comme type un pointeur vers une classe abstraite VDrawer. _vDrawer peut alors pointer soit vers VDrawer2d, soit vers VDrawer3d.
    VDrawer2d et VDrawer3d héritent aussi d'une classe Singletonqui contient une méthode statique kill(), à laquelle j'aimerais pouvoir accéder à partir de _vDrawer.

    Voici mon code actuel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VEngine::getInstance()->getVideoDrawer()::kill();
    getVideoDrawer() retourne évidement _vDrawer.
    Evidement, le ::kill() ne fonctionne pas comme il devrait ;-)

    Il faut aussi ajouter que le VDrawer n'hérite pas de Singleton, tandis que VDrawer2d et VDrawer3d le font. C'est peut-être la cause du problème.

    Merci d'avance !

    Edit: J'ai essayé ceci aussi, mais il semblerait que typeid ne serve qu'à comparer 2 classes différentes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typeid(*(VEngine::getInstance()->getVideoDrawer()))::kill();
    Edit2: On pourrait aussi faire hériter VDrawer de Singleton pour ne pas avoir d'héritage multiple, mais, vous vous en doutez, VDrawer est un Builder et le faire hériter de la classe Singleton l'obligerait à devenir une classe template pour permettre aux classes VDrawer2d et VDrawer3d de devenir des singletons aussi.
    Jusque là, c'est faisable sans trop de problèmes, mais ça détruit tout l'intéret du builder puisque je serais obligé de déclaré _vDrawer comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VDrawer<VDrawer2d> *_vDrawer;
    Edit3: Solution temporaire trouvée: créer une méthode non-static kill dans VDrawer. Elle serait définie de cette manière dans VDrawer2d par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void VDrawer2D::kill() {
    	VDrawer2D::kill();
    }
    Malgré ça, je n'aime pas avoir ce genre de bidouille dans mon code s'il y a moyen de l'éviter. J'ai cependant bien peur que ce ne soit possible dans mon cas.

  2. #2
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Je voudrais être sûr de comprendre : VEngine::getInstance() renvoie un singleton de VEngine, et dessus getVideoDrawer() renvoie un singleton de VDrawer ? Dans ce cas, je pense que la syntaxe serait plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VEngine::getInstance()->getVideoDrawer()->kill();
    si getVideoDrawer renvoie un pointeur, ou avec un '.' s'il renvoie une référence ; mais c'est peut-être encore plus simple comme ça :

    si VDrawer est bien un singleton.

    Ceci-dit, si VDrawer n'hérite pas de Singleton, et qu'il ne déclare pas une méthode kill(), je pense pas que ça puisse marcher aussi facilement ; il te faudra probablement passer par un dynamic_cast pour vérifier si l'instance renvoyée et bien un VDrawer2d ou un VDrawer3d qui eux possèdent bien une méthode kill().

    A voir si tu n'as pas un problème de conception ?

  3. #3
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2006
    Messages : 59
    Par défaut
    Tout d'abord, merci de ta réponse.

    Citation Envoyé par Noxen Voir le message
    Je voudrais être sûr de comprendre : VEngine::getInstance() renvoie un singleton de VEngine, et dessus getVideoDrawer() renvoie un singleton de VDrawer ? Dans ce cas, je pense que la syntaxe serait plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VEngine::getInstance()->getVideoDrawer()->kill();
    Effectivement, getVideoDrawer renvoi un singleton du drawer sélectionné. Ta solution est effectivement la plus simple, mais elle nécessite de rajouter une deuxième fonction kill non static dans VDrawer2d/3d ou dans Singleton. Je n'aime pas avoir deux fonctions avec la même utilité, je considère cela comme de la bidouille, et tout le problème vient de là, néanmoins, je pourrais aussi supprimer la méthode statique et ne garder que la méthode non-statique. C'est d'ailleurs tout à fait envisageable comme solution avec comme unique risque de devoir à un instant charger le singleton pour pouvoir le détruire (dans le cas où il n'est pas encore instancié).
    Je pense que je vais faire comme ça, mais je voudrais tout de même savoir s'il est possible d'utiliser une méthode statique d'une classe fille à partir d'un pointeur de son instance (quand la méthode statique est déclarée dans la classe mère).

    ... mais c'est peut-être encore plus simple comme ça :
    si VDrawer est bien un singleton.
    Dans ce cas si, VDrawer n'est pas un singleton alors que toute ses filles le seront à coup sure. C'est peut-être en effet un défaut de conception, mais je ne vois pas comment passer outre (toute suggestion bienvenue) car je devrais définir VDrawer comme classe template pour que ces filles puissent aussi être des singletons. Dans ce cas, je serais obligé de déclaré le pointeur vers VDrawer avec son paramètre de template pointant soit vers VDrawer2d, soit vers VDrawer3d, ce qui supprimerait l'intérêt du Builder VDrawer car on ne pourrait plus choisir dynamiquement entre VDrawer2d et VDrawer3d (sauf en utilisant 2 variables).

    Ceci-dit, si VDrawer n'hérite pas de Singleton, et qu'il ne déclare pas une méthode kill(), je pense pas que ça puisse marcher aussi facilement ; il te faudra probablement passer par un dynamic_cast pour vérifier si l'instance renvoyée et bien un VDrawer2d ou un VDrawer3d qui eux possèdent bien une méthode kill().
    Hehe, je suis bien dans ce cas si: VDrawer2d/3d héritent toutes les deux à la fois de VDrawer et de Singleton Le problème reste le même que dans le paragraphe précédent avec un dynamic_cast: il faudra obligatoirement définir le cast en VDrawer2d ou VDrawer3d, ce qui enlève encore une fois l'utilité d'un builder.

  4. #4
    Membre confirmé Avatar de deeal
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    218
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 218
    Par défaut
    si c'est une methode static, tu n'as pas besoin de retourner une instance de quoi que ce soit non
    pourquoi tu n'appelles pas directement
    VDrawer::kill()?

    D

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    A vrai dire, j'ai énormément de mal à comprendre pourquoi passer par une instance de singleton pour... obtenir l'instance unique d'un autre singleton...

    De toute évidence, tu a mal évalué les responsabilités de tes classes et les relations qui les unissent

    Il se peut qu'un singleton doive s'assurer de l'existence d'un autre (voir le fiasco dans l'ordre d'initialisation, dans la fAQ), mais, de manière générale, si un objet doit avoir un comportement polymorphe mais n'exister que sous la forme d'une instance unique, il ne faut jamais que la classe de base de cet objet soit un singleton.

    Si un singleton doit gérer un objet polymorphe, il doit avoir comme seule responsabilité la création et la destruction de l'objet en question, et la seule relation qui peut exister entre le singleton et la classe de base serait de l'ordre de la composition.

    Au final, cela pourrait ressembler à
    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
    /* une classe rajoutée: un singleton qui "porte" l'objet polymorphe */
    class DrawHolder
    {
        public:
            static DrawHolder& instance()
            {
                if(!inst)
                    inst = new DrawHolder;
                return *inst;
            }
            static void kill
            {
                delete inst;
                inst = NULL;
            }
            /* méthode (non statique) renvoyant le Drawer */
            Drawer* view()
            {
                return draw;
            }
            /* méthode (non statique) permettant de changer la vue */
            void changeView()
            {
                d3 = d3^1; // fait passer d3 de true à false et inversément
                /* libere la mémoire de la vue précédente */
                delete draw;
                /* alloue la mémoire à la nouvelle vue; */
                draw = (d3? new Drawer3D ; new Drawer2D);
            }
        private:
            /* par défaut, nous considérons que la vue sera 3D */
            DrawHolder():d3(true) 
            {
                draw = new Drawer3D;
            }
            ~DrawHolder()
            {
                delete draw;
            }
            Drawer* draw;
            bool d3; /* permet de savoir si l'affichage est effectué en 3D
    }
    Et nous aurions l'arborescence suivante au niveau des Drawer:
    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
    class Drawer
    {
        public:
        /* tout ce qui "va bien" */
        virtual void draw();
    };
    class Drawer2D : public Drawer
    {
        public:
            virtual void Draw();
    };
    class Drawer3D : public Drawer
    {
        public:
            virtual void Draw();
    };
    Le singleton tel que représenté s'écarte fortement du pattern builder, mais il peut très facilement finir par s'en rapprocher, si tu rajoute des méthodes (non statiques) qui permettent de gérer d'autre parties qui me sont restées inconnues
    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 averti
    Profil pro
    Étudiant
    Inscrit en
    Août 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2006
    Messages : 59
    Par défaut
    Tout d'abord, merci de vos 2 réponses !


    Deaal:
    VDrawer::kill() ne pourrait pas fonctionner vus que VDrawer n'hérite pas de Singleton et ne comporte donc pas la méthode kill(). Ou peut-être que s'il en héritait, VDrawer::kill() aurait le même effet que VDrawer2d::kill() ?


    koala01:
    Tu as tout à fait raison ! Pas besoin de transformer ton code en builder ou quoi que ce soit, je peux le laisser comme ça en mettant les constructeurs des Drawers privés et en définissant les Drawers comme amis de l'Holder. J'ai confondu ma définition de builder avec celle d'un Factory ultra simplifié (honte à moi !).

    J'ai trouvé le problème que posait mon architecture actuelle, mais il me reste quelques questions.

    Si un singleton doit gérer un objet polymorphe, il doit avoir comme seule responsabilité la création et la destruction de l'objet en question, et la seule relation qui peut exister entre le singleton et la classe de base serait de l'ordre de la composition.
    - Ceci dût à la sémantique ou à un problème technique envisageable ? Actuellement, le seul avantage technique que je vois est que cela encapsule mieux le fonctionnement du holder.

    - Ce pattern "Holder" porte-t-il un nom ?

    En tout cas, encore merci énormément !

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 24/05/2011, 11h05
  2. Réponses: 4
    Dernier message: 10/10/2010, 11h46
  3. Utiliser une méthode non-static dans une méthode static
    Par mcfly37 dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 18/08/2010, 11h41
  4. Réponses: 2
    Dernier message: 05/03/2010, 14h15
  5. Réponses: 2
    Dernier message: 26/02/2008, 18h28

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