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 :

Classe abstraite : utilisation des methode virtuelles pures dans la classe même


Sujet :

C++

  1. #1
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Je crée une classe abstraite PLAY, qui devient abstraite avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual MediaType PLAY::getMedia() =0;
    J'en hérite des PLAY_SOUND.class, PLAT_VIDEO.class, etc.
    qui en implémentant getMedia() vont concrétiser.

    Problème, le debuggeur refuse mon appel de getMedia()
    dans le constructeur de PLAY.classe_abstraite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    classe PLAY{
     
    private:
    MediaType truc;
     
    public:
    PLAY(){
       truc = getMediaType();
       truc->play();
    };
    je débute avec ce genre de concept, mais je fais une erreur de gros newbie ou bien ?
    Pourtant en concrétisant getMedia(), en théorie, c'est classieux...

    Pas possible dans un constructeur ?

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Règle 4751 : jamais tu n'appelleras de fonctions virtuelles (ou virtuelles pures) dans un constructeur petit scarabée.

  3. #3
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Merci ram. J'ai compris, ni dans un destructeur par ailleurs.



    En revanche y a t il des techniques communément utilisées pour palier à ce genre de pulsions ?
    J'ai mis un booléen dans le constructeur, booléan qui conditionne (une fois seulement) l'appel de ma "virtuelle pure"...

    ...et devinez où ? Dans la méthode "paint" bien sûr (je travaille sur une GUI)

    Je sens que c'est la grande classe cette technique.

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

    Informations professionnelles :
    Activité : aucun

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

    J'ai vaguement l'impression que ce que tu cherche à faire, c'est d'implémenter le concept de singleton...

    Dés lors, plutot que de travailler avec des méthodes virtuelles ou virtuelles pures, tu devrais envisager de travailler avec des fonctions et des variables membres statiques.

    L'une des implémentations du concept de singleton que j'aime le plus est celle à base de CRTP (Curiously Recurying Template Patern):
    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
    //dans un fichier d'en-tete unique
    #ifndef TSINGLETON_H
    #define TSINLGLETON_H
     
    template <class T>
    class TSingleton
    {
        public:
            static T& instance() //getMedia, pourquoi pas ??
            {
                if(!inst)
                    inst = new T;
                return *inst;
            }
            static void destroy()
            {
                if(inst)
                {
                    delete inst;
                    inst = NULL;
                }
            }
        private:
            T* inst;
            /* refusons l'acces au constructeur et au destructeur */
            TSingleton(){}
            ~TSingleton(){}
    };
    template<T> T*::TSingleton<T>::inst = 0;
    #endif // TSINGLETON_H
    Comme, en plus, il semblerait que tu veuille que tes classes dérivent de Play, il faut voir dans quelle mesure le singleton agit:

    Soit, il n'y a qu'une instance de Play à un moment donné, et dans ce cas, tu applique le CRTP directement sur la classe Play:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Play : public TSingleton<Play> //ca, c'est le CRTP
    {
        public:
            friend class TSingleton<Play>;
            /* les fonctions qui vont bien */
        private:
            /* refusons l'acces au constructeur et au destructeur
             * TSingleton y accede grace à son amitié avec la classe
             */
            Play();
            virtual ~Play();
    };
    soit, tu accepte l'idée qu'il y ait plusieurs instances dérivées de Play, mais tu veux qu'il n'y ai jamais plus d'une instance de chaque type, et, dans ce cas, tu applique le CRTP sur les classes dérivées de Play:
    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
    class Play
    {
        public:
            /* les fonctions qui vont bien */
        protected:
            /* le constructeur et le destructeur ne sont accessibles qu'aux
             * classes qui dérivent de Play
             */
            Play(){}
            virtual ~Play(){}
    };
    /* et les classes dérivées de Play applique le CRTP
    class DeriveeDePlay : public Play,
                          public TSingleton<DeriveeDePlay >
    {
        public:
            friend class TSingleton<DeriveeDePlay >;
        private:
            /* refusons l'acces au constructeur et au destructeur
             * TSingleton y accede grace à son amitié avec la classe
             */
            DeriveeDePlay(){}
            virtual ~DeriveeDePlay (){}
    };

  5. #5
    Membre actif Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Points : 203
    Points
    203
    Par défaut
    Ca se rapproche de ce que je veux faire, je vais étudier le concept de singletont.

    Cependant ce que je peux déjà répondre à ton exemple, c'est que typiquement dans mon projet, je vais avoir :
    * plusieurs classes dérivées de PLAY (actuellement 4)
    * un grand nombre d'instances pour chacune de ces classes.

    Je me rends compte cependant que toutes les classes dérivées se ressemblent beaucoup finalement, elles ne font que donner un Media, qui est lui-même construit pour être audio, video, etc...
    Auquel cas je n'aurais pas vraiment besoin de dériver PLAY, mais ca deviendrait plus confus au niveau de l'architecture et la lecture du code.
    Car pour l'instant il ressemble à ca :
    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
     
    classe PLAY{
     
    private:
    MediaType truc;
    bool isMediaDefined = false;
     
    public:
    PLAY(){
    };
     
    void paint(Graphics &g){//appelé automatiquement à la création
     
       if(!isMediaDefined){
         truc = getMediaType();
         isMediaDefined = true;
       };
    };
     
    void getMediaType() =0 {
       return new MediaType();
    }
     
     
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     
    class PLAY_VIDEO : public PLAY {
     
    private:
    VideoMedia maVideo = new VideoMedia();
     
    public :
       PLAY_VIDEO(){};
       void getMediaType(){
           return maVideo;
       }; 
    };


    nb : accessoirement :
    * PLAY dérive elle même d'une classe d'une API


    __________________
    "Faites simple, aussi simple que possible mais pas plus" A.Einstein

Discussions similaires

  1. Réponses: 13
    Dernier message: 23/05/2013, 20h38
  2. Réponses: 13
    Dernier message: 20/10/2008, 16h36
  3. classe abstraite avec des methodes manquantes
    Par kkkkkk dans le forum Langage
    Réponses: 6
    Dernier message: 17/10/2007, 15h13
  4. Réponses: 15
    Dernier message: 05/07/2007, 01h29
  5. Réponses: 1
    Dernier message: 03/04/2007, 12h02

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