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 :

Probleme "undefined reference to `vtable for Atomes'"


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut Probleme "undefined reference to `vtable for Atomes'"
    Bonjour/bonsoir à tous.

    J'ai un petit soucis de programmation. Je suis limite "newbie" dans le domaine, puisque c'est un exercice de TP, et la majeure partie étant faite par la prof.. ^^' Bref, elle n'a pas réussi à m'expliquer comment résoudre mon probleme de vtable.

    voici l'erreur :

    obj\Debug\main.o||In function `_ZN18FonctionNVariablesD0Ev'
    C:\Users\Prophete\Desktop\test c++\TP4\main.cpp.text$_ZN6AtomesD1Ev[Atomes::~Atomes()]+0xb)||undefined reference to `vtable for Atomes'|
    C:\Users\Prophete\Desktop\test c++\TP4\main.cpp.text$_ZN6AtomesD2Ev[Atomes::~Atomes()]+0xb)||undefined reference to `vtable for Atomes'|
    C:\Users\Prophete\Desktop\test c++\TP4\main.cpp.text$_ZN6AtomesC2Ei[Atomes::Atomes(int)]+0x1f)||undefined reference to `vtable for Atomes'|
    C:\Users\Prophete\Desktop\test c++\TP4\main.cpp.text$_ZN6AtomesC1Ei[Atomes::Atomes(int)]+0x1f)||undefined reference to `vtable for Atomes'|
    ||=== Build finished: 4 errors, 0 warnings ===|

    voici les fichiers sources dans le fichier ZIP.

    J'espère que vous pourrez m'aider!!
    Je vous remercie tous d'avance ^^


    PS :
    - J'ai cherché sur google, et donc aussi sur le forum.. Et disons que j'ai "rien compris" aux solutions. Notament celle qui parle d'utiliser moc où d'autre... Mon niveau est vraiment mauvais ^^'

    - Les fichiers "vecteur.h" et "vecteur.cpp" sont fournis pré-fait, donc il n'y a pas d'erreur dedans.

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

    Honnêtement, si le code présenté est en grosse partie fourni par le prof, il y a vraiment de quoi se poser des questions sur sa compétence sur le sujet (ou alors, c'est toi qui rêvais énormément pendant les cours "théoriques", et qui n'a rien compris à ce qu'elle t'expliquait )

    Déjà, le destructeur de la classe FonctionVariable (quel drôle de nom pour une classe ) devrait soit être public et virtuel, soit protégé et non virtuel (cf: cette entrée de la FAQ, et cette autre), et il en va de même pour toutes les classes qui dérivent de manière directe ou indirecte de FonctionVariable (Atmomes et dérivées)

    Ensuite, et c'est sans doute là que prend la naissance de ton problème, la fonction potentiel de la classe Atomes n'est pas définie (mais est déclarée comme fonction virtuelle).

    Il y a donc deux possibilités:
    Soit tu transforme cette fonction en fonction virtuelle pure, avec pour conséquence de rendre ta classe Atome abstraite (et donc nécessité de redéfinir cette fonction pour les classes dérivées qui devront être instanciables)... Allez, encore un petit coup de FAQ
    Soit tu fournis un "comportement de base" qui soit adapté aux atomes "sans autres information"

    De plus, mais ce n'est désormais plus qu'un détail, je ne suis pas vraiment persuadé qu'il soit opportun de faire hériter un atome (si tel est bien l'utilisation qui est faite de la classe de même nom) d'une... fonction variable.

    Enfin, mais bon, est-ce que cela change encore quelque chose ,je suis des plus surpris de rencontrer le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Atomes (int init): FonctionNVariables(2*init) {init=n_at;};
    pour le constructeur, car il modifie la variable locale init, après que son utilisation en a pris fin, et... juste avant de quitter la fonction (et donc, avant que la variable init soit détruite) ... Cela n'a strictement aucun sens, et ce, d'autant plus qu'il lui assigne... une valeur non initialisée
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    effectivement,

    j'ai mal lu l'énoncé ^^'


    Déclarez une méthode virtuelle pure virtual double potentiel(double deltax, double deltay)=0; qui représente le potentiel V (∆x, ∆y) de l'équation (4.8).

    donc j'ai mis cette fois :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Atomes: public FonctionNVariables
    {
        protected :
    	int n_at; //nombre d'atomes
     
    public:
    	Atomes (int init): FonctionNVariables(2*init) {init=n_at;};
    	Vecteur init_P(double R);
    	void ecrire_coord(const Vecteur& P,const char* fichier_atomes);
    	virtual double potentiel(double deltaX, double deltaY)=0;
    	double eval(const Vecteur& P);
    };

    cela donne donc comme erreur : (cette fois je suis sous linux ^^' )

    thode num/TP4/main.cpp||In function ‘int main()’
    thode num/TP4/main.cpp|115|erreur: cannot declare variable ‘A’ to be of abstract type ‘Atomes’|
    thode num/TP4/Atomes.h|14|note: because the following virtual functions are pure within ‘Atomes’
    thode num/TP4/Atomes.h|22|note: virtual double Atomes::potentiel(double, double)|
    ||=== Build finished: 1 errors, 0 warnings ===|

  4. #4
    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
    C'est donc que tu essaye d'instancier un Atome, or, c'est devenu une classe abstraite vu que tu as une fonction virtuelle pure (virtual double potentiel( double deltaX, double deltaY ) = 0 ; )
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    je tente quelques petites modif, mais cela me donne d'autres erreurs... Je vais essayer continuer a voir ce qu'il y a à modifier ^^

  6. #6
    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
    Citation Envoyé par Ashitaka26 Voir le message
    je tente quelques petites modif, mais cela me donne d'autres erreurs... Je vais essayer continuer a voir ce qu'il y a à modifier ^^
    Si tu ne nous en dis pas d'avantage sur ce que tu as modifié ou sur les erreurs que tu obtiens, nous aurons du mal à t'aider à apporter une solution

    Ceci dit, pour en revenir à ton problème d'impossibilité de déclarer un objet de type Atome:

    Si tu déclares une fonction virtuelle pure (c'est ce que représente le fameux =0 qui suit ta fonction potentiel ), tu indiques deux choses au compilateur:

    1- que tu ne dispose pas des données nécessaires pour définir le comportement (sinon, on peut croire que tu l'aurais défini )

    2- que les classes qui héritent de la classe que tu définis et que tu souhaite pouvoir instancier devront définir ce comportement.

    Cela revient strictement à dire au compilateur "je sais que les classes dérivées disposeront d'un comportement nommé (le nom de la fonction), mais là, je ne peux absolument pas le fournir!!!

    Le compilateur, de manière générale, a horreur du vide et, si tu as une classe pour laquelle un comportement n'est pas définis, il refusera purement et simplement de créer une instance de cette classe, car il ne saura pas que faire si, d'aventure, tu décide d'invoquer cette fonction (du moins, lorsqu'il est au courent, sinon, c'est l'éditeur de liens qui se plaindra de ne pas trouver le symbole correspondant dans le code binaire ).
    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
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    nah je suis perdu la...

    maintenant j'ai :

    thode num/TP4/main.cpp||In function ‘int main()’: |
    thode num/TP4/main.cpp|129|erreur: cannot declare variable ‘A’ to be of abstract type ‘Atomes’|
    thode num/TP4/Atomes.h|9|note: because the following virtual functions are pure within ‘Atomes’: |
    thode num/TP4/FonctionNVariables.h|42|note: virtual double FonctionNVariables::eval(const Vecteur&)|
    ||=== Build finished: 1 errors, 0 warnings ===|
    Je sais plus où et quoi faire.
    Pour avoir cette erreur, j'ai amputer le programme des parties faisant appel à :

    // virtual double potentiel(double deltaX, double deltaY)=0;
    // double eval(const Vecteur&P);

    ainsi que les 2 classes AtomesVdW et AtomesCov ....

    une idée? (c'est à rendre pour demain ~~ je le sens mal)

  8. #8
    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
    Si tu déclares une fonction virtuelle pure dans une classe et que les classes dérivées ne la redéfinissent pas, tu te retrouves avec une classes dérivée... tout aussi incomplète que si tu y avait placé directement la fonction virtuelle pure.

    Et cela transforme doncla classe dérivée en... classe abstraite.

    C'est la raison pour laquelle, si tu veux instancier une classe, tu dois veiller à ce que le comportement de l'ensemble des fonction virtuelles soit défini au plus tard dans la classe que tu souhaites instancier.

    Tu dois donc avoir:
    • une définition des fonctions virtuelles dont le comportement est adapté à ta classe (si, du moins, le comportement défini pour la classe de base ne correspond pas)
    • la définition de l'ensemble des fonctions virtuelles pures héritées
    • le cas échéant, les fonctions propres à la classe envisagée
    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

  9. #9
    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
    Pour te permettre de comprendre:
    Soit une classe "ancêtre" A qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class A
    {
        public:
            virtual void foo() = 0;
    };
    Comme tu peux le remarquer, foo est une fonction virtuelle pure, ce qui fait que A est... une classe abstraite.

    Imaginons que la classe B hérite de la classe A:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class B : public A
    {
        public:
            /* foo() n'est pas redéfinie... elle reste donc une fonction
             * virtuelle pure
             */
            virtual void bar() = 0;
    };
    Il y a dans B deux fonctions fonctions virtuelles pures qui rendent B abstraite

    Suit la classe C qui hérite de B:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class C : public B
    {
        public:
            virtual void bar(){ /*...*/ }
    };
    C dispose de ce qu'il faut pour implémenter bar, et il est donc logique de... définir le comportement de cette dernière, mais... foo() n'est toujours pas définie: C est donc toujours une classe abstraite.

    Il en irait de même avec une classe D qui prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class D : public B
    {
        public:
            virtual void foo(){ /*...*/ }
    };
    (si ce n'est que l'on a inversé les noms de fonctions )

    Si tu veux pouvoir implémenter une classe qui hérite directement de B, tu dois... implémenter les deux fonctions virtuelles pures (foo et bar), sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class E : public B
    {
        public:
            virtual void foo(){/*...*/}
            virtual void bar(){/*...*/}
    };
    Mais tu peux également décider de faire dériver une classe de C ou de D:
    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
    class F : public C
    {
        public:
            /* si tu veux pouvoir instancier F, tu dois définir... foo, qui est
             *  encorevirtuelle pure
             */
            virtual void foo(){/*...*/}
            /* et tu peux, si cela a un sens, redéfinir le comportement de bar */
            virtual void bar(){/*...*/}
    };
    /* le principe serait similaire pour une classe hértiant de  D
     * si ce n'est que la fonction à définir en priorité serait... bar
     */
    class G : public D
    {
        public:
            /* si tu veux pouvoir instancier F, tu dois définir... bar, qui est
             * encore virtuelle pure
             */
            virtual void bar(){/*...*/}
            /* et tu peux, si cela a un sens, redéfinir le comportement de foo */
            virtual void foo(){/*...*/}
    };
    Et bien sur, rien ne t'empêche, si cela a un sens, de faire hériter une classe de A et d'implémenter la fonction foo (afin de pouvoir l'instancier), voire, de faire hériter une classe de E, F ou G, en décidant éventuellement, de redéfinir le comportement de foo ou de bar (bien que ces classes seraient de toutes manières instanciables, car non abstraites )
    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

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    Ok, je regarde ^^
    merci du temps que vous prenez pour m'aider en tout cas

  11. #11
    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
    Citation Envoyé par Ashitaka26 Voir le message
    Quand vous dites :
    cela veut dire que mon "double virtual eval(const Vecteur& P)=0;" de FonctionNvariable.h est mauvais?
    Ca dépend pour quelle classe...

    Si c'est dans une classe abstraite, il a du sens.

    Si c'est dans une classe instanciable héritant de la classe abstraite, il faut... définir le comportement de la fonction.

    Si c'est une "nouvelle fonction" d'une classe instanciable (comprend: si cette fonction n'est pas déclarée dans une des classes de base), il faut réfléchir un peu:

    Si le comportement ne doit pas être adapté en fonction du type réel (parce que, quel que soit la classe dérivée au départ de laquelle on invoque la fonction, le comportement est clair et définitif), une fonction non virtuelle devrait être utilisée

    Si le comportement doit être adapté, mais que tu dispose des informations permettant de donner un comportement "de base", il faut créer une fonction virtuelle (mais non pure), et l'implémenter avec "le comportement de base".
    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

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    nah nah, selon le fascicule qui donne les nom des fonctions de chaque classes, ils précisent bien si c'est virtuel (pure) ou pas ^^

    bon par contre je dois m'absenter, je vais manger au resto universitaire... Et ensuite j'enchaine avec un autre cour de spectrométrie. Je reviens vers 16h ^^

    Merci a vous!

  13. #13
    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
    Citation Envoyé par Ashitaka26 Voir le message
    nah nah, selon le fascicule qui donne les nom des fonctions de chaque classes, ils précisent bien si c'est virtuel (pure) ou pas ^^

    bon par contre je dois m'absenter, je vais manger au resto universitaire... Et ensuite j'enchaine avec un autre cour de spectrométrie. Je reviens vers 16h ^^

    Merci a vous!
    Oui, dans la classe de base...

    Mais, si tu ne définis pas le comportement de la fonction déclarée comme virtuelle pure dans la classe de base pour la classe dérivée, ta fonction reste virtuelle pure dans la classe dérivée, et cette classe dérivée devient donc... de facto abstraite

    Or, une classe abstraite est... non instanciable
    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

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    j'ai résolu le problème :-) j'ai fait appel a ma classe virtuelle via d'autre classe.

    J'ai supprimé le fichier ZIP. Le document étant noté..
    En tout cas, je te remercie beaucoup de tout ton temps que tu m'as donné ^^

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

Discussions similaires

  1. [Error] undefined reference to `vtable for ?
    Par Some0ne dans le forum C++
    Réponses: 1
    Dernier message: 20/01/2011, 00h34
  2. Réponses: 1
    Dernier message: 19/07/2009, 22h37
  3. undefined reference to `vtable for Graphique'
    Par lilly91 dans le forum Débuter
    Réponses: 11
    Dernier message: 23/06/2009, 17h41
  4. undefined reference to `vtable for
    Par zalalus dans le forum Qt
    Réponses: 13
    Dernier message: 27/05/2009, 15h27

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