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 :

Erreur de link


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 72
    Points : 56
    Points
    56
    Par défaut Erreur de link
    Bonjour et bonnes fêtes à tous,

    Je travail actuellement sur un projet sur lequel je reste bloqué.
    En effet, je créer une classe de cette façon :

    class LoadState : public GameState, public ResourceGroupListener
    {
    ...
    };

    Si j'hérite seulement de l'une des classes (GameState ou ResourceGroupListener), je n'ai aucun problème de compilation.
    Par contre si je fais comme ci-dessus, c'est à dire hériter de deux classes de cette manière, je tombe sur l'erreur de link suivante que je ne comprend pas ... :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LoadState.obj : error LNK2019: symbole externe non résolu "public: virtual __thiscall LoadState::~LoadState(void)" (??1LoadState@@UAE@XZ) référencé dans la fonction "public: virtual void * __thiscall LoadState::`scalar deleting destructor'(unsigned int)" (??_GLoadState@@UAEPAXI@Z)

    Je sais pas si ça peut aider mais la classe LoadState est de type singleton.
    La classe ResourceGroupListener possède des fonctions virtuelles pures (que j'ai redéclarées dans ma classe).

    Pourriez-vous m'aider. En effet, je ne vois pas ce qui cloche ou peut clocher.
    Si vous aviez des pistes pour m'aider.

    Merci par avance.

    Olivier.

  2. #2
    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,

    La première idée qui me vienne à l'esprit, c'est que le destructeur de loadState n'est pas virtuel ou implémenté de manière inline que ce soit implicitement parce que implémenté directement dans la définition de la classe, ou explicitement.

    La deuxième chose qui me choque un peu est le fait qu'il s'agisse d'un singleton...

    Est-ce une propriété "nouvelle" par rapport à GameState et ResourceGroupListener ou est-ce une propriété héritée de l'un des deux

    S'il s'agit d'une nouvelle propriété, nous ferons comme si je n'avais rien dit, mais, s'il s'agit d'une propriété hérité de GameState ou de ResourceGroupListener, je ne peux m'empêcher de crier attention, danger...

    Les singletons font rarement (jamais ) de bons prétendants au titre de classe de base servant à l'héritage publique

    Enfin, c'est mon coté chipoteur qui parle, mais je ne peux m'empêcher, lorsque je croise un héritage publique dont j'ignore tout, de me poser la question de savoir s'il est effectivement cohérent de dire qu'un "truc" EST UN chose... Et c'est encore pis lorsque c'est un héritage multiple...

    Ainsi donc, étant donné que j'ignore tout de ton projet, est-il réellement cohérent de dire qu'un LoadState EST UN GameState et qu'il EST (tout à la fois) UN ResourceGroupListener

    Ne serait-il pas plus cohérent de dire qu'il est implémenté en terme de GameState et / ou de ResourceGroupListener

    Pire, s'agissant d'un singleton, on peut, décemment, considérer le fait que tu n'aura jamais besoin d'y recourir de manière polymorphique, ni (et encore moins) de créer une collection d'objets impliquant de l'utiliser de manière polymorphe...

    Je ne veux absolument pas dire qu'il ne faudra pas adapter un comportement propre au GameState ou au RessourceGroupListener dans ton objet de type LoadState, mais il ne devrait en tout cas jamais être question de considérer ton LoadState comme un GameState ou un RessourceGroupeListener, vu que, par définition, tu n'aura jamais qu'une instance unique de LoadState, à laquelle tu aura accès pour ainsi dire partout...

    Tout cela pour dire que, de prime abord, il ne me semble pas réellement opportun de placer une relation aussi forte que celle qui est mise en place par héritage publique entre ton LoadState et ses deux classes mères...
    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

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 72
    Points : 56
    Points
    56
    Par défaut
    Salut,

    d'abord merci pour ton aide .

    D'un point de vue conception, je pars apparemment sur un truc que tu trouve "sale" et vu que je suis pas très bon en programmation si tu peux m'orienter vers une architecture plus adaptée, ça me ferait progresser .

    Donc tu me demandais si c'était une propriété nouvelle par rapport à GameState et ResouceGroupListener, je répondrais que je considère que oui (ca veut pas dire que c'est le cas). J'explique brièvement la partie de code qui m'intéresse.

    Je fais un petit jeu. Dans ce jeu y a des "étapes". Y a donc l'intro, le menu, le jeu, ... Pour réaliser ça, j'ai une classe GameState qui est une classe abstraite. Elle sert à définir une structure pour chaque niveau (pour avoir une classe pour chaque "étapes"). J'ai donc tout mes niveaux (IntroState, MenuState, PlayState, LoadState) qui hérite de gameState.

    Dans ma classe LoadState je dois aussi faire appel à ResourceGroupListener qui est aussi une classe abstraite avec des méthodes callback qui sont appelées quand mes ressources se chargent.

    D'où cette architecture de une classe qui hérite de deux autres trucs.
    Qu'en penses-tu ?

    Sinon, j'ai "résolu" mon problème en mettant le constructeur comme-ci :
    LoadState(){} au lieu de LoadState();

    Je comprend pas pourquoi ça enlève le bug ... Dans mes autres classes je fais un LoadState(); et ça a jamais posé de soucis (j'imagine que c'est "sale" aussi donc).

    Donc je considère que j'ai résolu mon bug à part si on me propose une structure mieux. Car ca compile et se lance maintenant mais je sais pas pourquoi ...

    Merci

  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
    Citation Envoyé par Morrigan Voir le message
    Je fais un petit jeu. Dans ce jeu y a des "étapes". Y a donc l'intro, le menu, le jeu, ... Pour réaliser ça, j'ai une classe GameState qui est une classe abstraite. Elle sert à définir une structure pour chaque niveau (pour avoir une classe pour chaque "étapes"). J'ai donc tout mes niveaux (IntroState, MenuState, PlayState, LoadState) qui hérite de gameState.
    Jusque là, je suis d'accord, mais, quand tu écris
    Dans ma classe LoadState je dois aussi faire appel à ResourceGroupListener qui est aussi une classe abstraite avec des méthodes callback qui sont appelées quand mes ressources se chargent.

    D'où cette architecture de une classe qui hérite de deux autres trucs.
    Qu'en penses-tu ?
    Je dis AH, NON...
    Tu le dis toi même, tes états utilisent des ResourceGroupListener...

    Cela ne veut absolument pas dire que tes états peuvent être considérés comme des ResourceGroupListener ...

    Cela veut "juste" dire qu'il y a une association entre les deux types, qui est sans doute proche de l'agrégation.

    D'autant plus que, ta classe ResourceGroupListener étant abstraite, il y a de fortes chances pour que les différents états (on parle ici de LoadState, mais c'est aussi valable pour IntroState et tous les autres) aient en réalité recours à une "spécialisation" de la classe ResourceGroupListener (des classes telles que "RessourceLoaderListener", "RessourceIntroListener" ou autres qui, elles, héritent... de ResourceGroupListener)

    Ta classe de base GameState disposerait donc d'un pointeur vers un objet de type (ou pouvant passer pour) ResourceGroupListener, qui pointerait vers... l'instance de la classe concrète correspondant au type d'état que tu manipule réellement...

    Au final, au lieu d'avoir un code 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
    class GameSate
    {
        /*...*/
    };
    class RessourceGroupListener
    {
        /*...*/
    };
    class LoadState : public GameState, public RessourceGroupListener
    {
    };
    class IntroState : public GameState, public RessourceGroupListener
    {
    };
    tu aurais un code 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    class RessourceGroupListener
    {
        /*...*/
    };
    class GameSate
    {
        /*...*/
        GameState(RessourceGroupListener  r=0):rgl_(r){}
        /* devrait etre implémenté dans un fichier *.cpp, 
         * mais présenté ici "par flegme"
         */
        virtual ~GameState()
        {
            delete rgl_;
        }
        void callOne(){rgl_->callBackOne;}
        void callTwo(){rgl_->callBackTwo;}
        protected:
        private:
            RessourceGroupListener * rgl_;
    };
     
    class LoadState : public GameState
    {
        public:
            LoadState():GameState( new RessourceLoaderListener)
            {
            }
            /*...*/
    };
    class IntroState : public GameState
    {
        public:
            IntroState : GameState( new RessourceIntroListener)
            {
            }
            /*...*/
    };
    Évidemment, j'ai choisi, par facilité, de créer les instances de type RessourceLoaderListener et RessourceIntroListener "sur place", mais d'autres solutions plus adaptées existent, comme le recours à une fabrique, voire, à un gestionnaire d'objets
    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 du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 72
    Points : 56
    Points
    56
    Par défaut
    Salut,

    Mouarf c'est vrai à coder à l'arrache sans reflechir sur la conception, j'en arrive à des trucs qui une fois dit me semble logique

    C'est vrai que j'aurais du faire une agrégation au lieu d'un héritage.
    Je vais me refaire un petit diagramme des classes pour remettre les choses dans le bonne ordre avant de continuer.

    Merci de ton aide

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

Discussions similaires

  1. erreur de link
    Par meli0207 dans le forum MFC
    Réponses: 6
    Dernier message: 04/05/2007, 10h17
  2. template et erreur de link
    Par Willand dans le forum Langage
    Réponses: 12
    Dernier message: 05/12/2006, 21h19
  3. erreur de link(age) g++
    Par corwin dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 05/05/2004, 11h33
  4. [wxWindows] Erreur de link pour ODBC
    Par ovh dans le forum wxWidgets
    Réponses: 3
    Dernier message: 28/01/2004, 15h38
  5. DirectDrawCreate erreur de link
    Par Ing_Ben dans le forum DirectX
    Réponses: 1
    Dernier message: 01/12/2002, 18h46

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