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 :

instanciation de classe dérivée de classe abstraite


Sujet :

C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 43
    Points : 22
    Points
    22
    Par défaut instanciation de classe dérivée de classe abstraite
    Bonjour,

    je bute sur un probleme et j'aurais bien besoin d'aide pour m'en sortir:


    J'ai une classe abstraite "Engine", qui contient une fonction virtuelle pure "init()".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Engine
    {
        public:
            Engine(EngineList* engines);
            virtual ~Engine();
            virtual void init() = 0 ;
        protected:
            EngineList* engines;
     
        private:
    };
    Je dérive cette classe en une classe "Game Engine", une autre "FrameEngine", etc. ou j'implémente une fonction init() en dur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class GameEngine : public Engine
    {
        public:
            GameEngine( long resX, long resY, bool cursor, bool delay, int timePerFrame, EngineList* engines);
            virtual ~GameEngine();
            virtual void init(long resX, long resY, bool cursor, bool delay, int timePerFrame); // fonction implémentée
        protected:
            EngineList* engines;
        private:
    };


    J'ai besoin de créer un tableau avec un pointeur vers chacun de mes Engines (GameEngine, FrameEngine, etc.).

    Je crée donc un Engine*, je crée les objets qui vont bien, et quand je lance la fonction init, le compilateur rale comme quoi la classe Engine est virtuelle.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Engine* list[2];
     
    list[0] = new GameEngine(....)//  je declare la liste de parametres qui vont bien
    Qqn peut me dire comment me sortir de ce probleme?

    Merci!

    Z.

  2. #2
    Membre confirmé
    Homme Profil pro
    Consultant MOA
    Inscrit en
    Juillet 2004
    Messages
    289
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Consultant MOA
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2004
    Messages : 289
    Points : 635
    Points
    635
    Par défaut
    Ta méthode Init vituelle pure n'a pas les mêmes arguments que tes Init virtuelle dure, donc elles sont considérées comme 2 méthodes distinctes, et non comme de l'héritage.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 43
    Points : 22
    Points
    22
    Par défaut
    OK... je vois...
    mais du coup, si je ne déclare pas la fonction init au niveau de Engine,
    je peux instancier mon gameEngine sur un pointeur engine*, mais le compilateur plante quandj'essaie d'acceder a la fonction init de mon GameEngine comme quoi init() n'existe pas dans la classe Engine.

    la seule solution que je trouve est de caster mes pointeurs Engine* en FrameEngine*... mais c'est pas terrbible non?

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

    Informations professionnelles :
    Activité : aucun

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

    C'est tout le problème propre à une analyse trop peu poussée que tu présente là...

    La question première que tu dois te poser est déjà de savoir s'il est opportun de faire passer un objet de type dérivé pour un objet de type de base...

    La réponse à cette question ne sera oui que... si tu veux faire cohabiter différents types dérivés dans une collection d'objets ET que tu peux te contenter d'utiliser uniquement les comportements connus par le type de base

    C'est à dire que, si tu veux travailler sur un objet du type dérivé, tu dois bel et bien... utiliser le type dérivé en question...

    Si, après avoir placé cet objet dans une collection d'objet passant pour le type de base, tu en viens à envisager le transtypage de l'objet, c'est, le plus souvent, que tu t'es gouré quelque part dans ta conception

    En plus, une fonction init (générale) est assez mal perçue et inutile en C++...

    L'un des concepts que l'on essaye généralement de respecter est ce que l'on désigne sous l'abréviation de RAII (Ressource Acquisition Is Initialisation), c'est à dire que, lorsque tu crées une variable d'un type donné, tu t'arrange pour qu'elle soit directement initialisée avec des valeurs te permettant de travailler avec...

    Le meilleur endroit pour effectuer cette initialisation est donc... le constructeur de ta classe

    Et lui, comme il ne peut en aucun cas être virtuel, il n'y a strictement aucun problème à ce qu'il prenne des arguments

    D'ailleurs, si tu est un peu attentif aux arguments passés à ton constructeur et à la fonction init, tu te rend compte... qu'ils sont fort similaires, à l'exception du pointeur sur un objet de type EngineList qui se trouve dans le constructeur

    J'en serais donc à me demander ce que tu peux bien vouloir faire avec ta fonction init, étant donné qu'elle fait visiblement double emploi avec ton constructeur

    Maintenant, s'il faut initialiser une partie des informations à un autre moment que lors de la construction, l'idée à garder en tête est de déléguer les responsabilités, ce qui signifie qu'il faille envisager de créer une fonction particulière par information à initialiser
    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

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 43
    Points : 22
    Points
    22
    Par défaut
    Super, merci pour la reponse!!
    Comme j'apprends C++ tout seul, ben je dois acquerir les principes de bonnes programmations sur le tas... et ce que tu me dis, ca m'aide!

    alors pour répondre a tes interogations:

    La réponse à cette question ne sera oui que... si tu veux faire cohabiter différents types dérivés dans une collection d'objets ET que tu peux te contenter d'utiliser uniquement les comportements connus par le type de base
    Ben c'est justement ce que je veux faire. je m'explique: j'ai un module "GameEngine" qui doit faire appelle a plusieurs autres modules, et ces sous modules doivent s'acceder regulierement les uns les autres.

    les solutions auxquelles j'ai pensé sont:
    1) je cree tous mes sous modules comme module de GameEngine, j'associe a chaque sous module un pointeur vers GameEngine et chaque fois qu'un sous module A doit faire appel a un sous module B, il faut faire un :
    moduleA->getGameEngine()->getModuleB();

    Je trouve ca pas terrible parce que je dois passer un pointeur vers GameEngine chaque fois que je veux creer un nouveau module, et ce pointeur est pas toujours facilement dispo depuis la ou je me trouve

    2) la solution a laquelle j'ai pensé: faire une classe EngineList, qui recense un pointeur vers tous mes sous modules, et dont je passe un pointeur a tous ms sous modules quand je les construit... mais a y regarder de plus pres c'est pas genial comme solution...
    En effet, j'avais mis tous mes modules, qui heritent de la classe Engine* dans un tableau de Engine*, et je les appelais avec un getEngine( engine x) ou engine est une liste enumérée des differents objets que je peux avoir...

    mais il est clair que si tous mes Engines derivent d'une meme classe, ils ont tous des methodes differentes d'ou la reponse a ta question:

    si tu veux faire cohabiter différents types dérivés dans une collection d'objets :

    oui!

    que tu peux te contenter d'utiliser uniquement les comportements connus par le type de base:

    ben la, non... mais au moins j'ai compris que j'avais pas bien compris le concept d'heritage.

    du coup......... ben du coup c'est quoi lamethode la plus propre pour faire communiquer mes sous modules entre eux???


    Pour le coup du constructeur et du init, j'avais lu chais plus trop ou que c'etait une bonne idée de pas initialiser les SDL et openGL dans du constructeur, mais plutot dans une init, parce que dans le cas ou on a une variable globale, on pouvait se retrouver dans une configuration bizarre ou tout plantait.... mais bon, c'est ptet pas une bonne raison

    merci encore

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Tu n'est pas très clair dans tes explications, et j'ai l'impression, à la lecture de celles-ci, que tu mélanges allègrement ce que tu appelle "module" et ce que tu appelle "engin"...

    A te lire, j'ai l'impression qu'il y a bel et bien des différences entre les deux, mais que, de ton coté, tu as une compréhension altérée de ces différence

    Pourrais tu nous fournir la définition de tes différentes classes, pour que nous puissions un peu "démêler" tout cela
    L'impression générale que ta solution passe sans doute par l'utilisation des design pattern visiteur, observateur ou médiateur (voire un "mix" de plusieurs de ces patterns), mais, pour l'instant, j'ai vraiment du mal à préciser

    Pour ton problème d'init:
    Pour le coup du constructeur et du init, j'avais lu chais plus trop ou que c'etait une bonne idée de pas initialiser les SDL et openGL dans du constructeur, mais plutot dans une init, parce que dans le cas ou on a une variable globale, on pouvait se retrouver dans une configuration bizarre ou tout plantait.... mais bon, c'est ptet pas une bonne raison
    C'est vrai...

    Mais il faut faire la distinction entre l'initialisation des données de la classe de l'initialisation de la SDL...

    La classe s'initialise dans... le cosntructeur... et devrait disposer de toutes les données nécessaires pour...initialiser SDL...

    De cette manière, il te "suffit" d'envisager le comportement init comme appelant SDL_init() (ou similaire), en lui passant... les membre de GameEngine

    Cela te donne une hiérarchie de classe proche de
    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
    class Engine
    {
        public:
            Engine();
            virtual ~Engine();
            virtual void init() = 0; /*effectivement aucun argument ;) */
    };
    class GameEngine : public Engine
    {
        public:
            GameEngine(long, long, bool, bool, int, EngineList*);
            virtual ~GameEngine();
            virtual void init()
            {
                SDL_init(resX, resY, cursor, delay, timePeFrame);
                /* ou tout comportement adéquat */
            }
        private:
            long resX; 
            long resY; 
            bool cursor;
            bool delay;
            int timePerFrame;
            EngineList* engines;
            /* peut etre un pointeur sur une structure SDL... qu'il faudra
             * penser à initialiser à NULL dans le constructeur et qui soit
             * capable de contenir le résultat de l'initialisation de SDL
             */ 
    };
    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

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    43
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 43
    Points : 22
    Points
    22
    Par défaut
    Module et Engine sont synonymes.... maintenant, j'admets que ca manquait un peu de clarté mon histoire.

    OK pour ta proposition de nouvelle architecture qui me semble pas mal...

    Quant à la définition de mes classes..... ben je peux pas la foirnir...parce qu'elle est encore mal définie.... ce qui se passe c'est que j'ai commencé il y a quelques mois a tester des trucs dans openGL pour voir... sans reflechir a une architecture précise...
    la j'essaie de reorganiser tout ces modules.... et du coup, j'essaie justement de déterminer la bonne architecture pour tout ca.

    merci pour les reponses!

    [Edit:]
    En fait..... en fait mon besoin est de pouvoir créer une architecture generique, ou je serai a meme d'ajouter un nouveau sous module du GameEngine et l'intégrer dans mon code sans avoir à tout remodifier a chaque fois...
    J'ai beau reflechir, je vois pas de solution elegante pour ca... j'imagine que c'est un probleme classique, il existe une solution standard a ce pb?

    merci

    Z.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par zeder59 Voir le message
    Module et Engine sont synonymes.... maintenant, j'admets que ca manquait un peu de clarté mon histoire.

    OK pour ta proposition de nouvelle architecture qui me semble pas mal...

    Quant à la définition de mes classes..... ben je peux pas la foirnir...parce qu'elle est encore mal définie.... ce qui se passe c'est que j'ai commencé il y a quelques mois a tester des trucs dans openGL pour voir... sans reflechir a une architecture précise...
    la j'essaie de reorganiser tout ces modules.... et du coup, j'essaie justement de déterminer la bonne architecture pour tout ca.
    Ok... Ce qu'il faut donc, c'est reprendre la conception depuis le début...

    Cela ne t'empêchera pas de copier coller une bonne partie du code, mais, généralement, il est préférable de ne pas mélanger un projet fait "sans objectif particulier" avec un projet bien précis
    [Edit:]
    En fait..... en fait mon besoin est de pouvoir créer une architecture generique, ou je serai a meme d'ajouter un nouveau sous module du GameEngine et l'intégrer dans mon code sans avoir à tout remodifier a chaque fois...
    J'ai beau reflechir, je vois pas de solution elegante pour ca... j'imagine que c'est un probleme classique, il existe une solution standard a ce pb?

    merci

    Z.
    Oui, et non...

    Il existe les "design patterns", ce sont des patrons de conceptions...

    C'est à dire ce sont des manières d'envisager les choses qui reviennent très régulièrement, mais qu'il faut adapter à ta situation propre

    Je suis intervenu dans la discussion Gestion lecteurs de cartes bancaires, dans laquelle, bien que le problème n'ait rien à voir avec OpenGl ni l'affichage en général, les points que j'ai abordés sont "conceptuellement" parlant proche de ce que tu veux faire...

    Intéresse toi particulièrement aux messagew #10
    #15 et
    #17

    Sinon, tu peux aussi passer par l'excellent article de laurent gomila sur la conception d'un moteur 3D

    Cela te permettra de te rendre compte que, ton problème est bel et bien connu

    N'hésite pas à venir poser des questions en cas de besoin
    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

Discussions similaires

  1. Réponses: 7
    Dernier message: 11/03/2010, 10h13
  2. Réponses: 3
    Dernier message: 23/09/2009, 09h52
  3. class pour table + class pour td = class td non fonctionnelle ?
    Par supergrey dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 28/05/2009, 08h13
  4. Réponses: 2
    Dernier message: 25/12/2008, 20h51
  5. Déterminer le type d'une class dérivée
    Par LDDL dans le forum MFC
    Réponses: 3
    Dernier message: 10/12/2004, 17h36

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