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 :

Problème de lien lors de la création d'un objet


Sujet :

C++

  1. #1
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut Problème de lien lors de la création d'un objet
    Bonjour tout le monde,

    Je débute en C++.

    J'ai créé un fichier .h dans lequel j'ai des classes.

    Dans le main, j'essaie de créer un objet de type CTabTriangles (qui est une des classes) et j'obtiens ces messages d'erreur :

    error LNK2001: unresolved external symbol "public: __thiscall CTabRectangles::~CTabRectangles(void)" (??1CTabRectangles@@QAE@XZ)
    principal.obj : error LNK2001: unresolved external symbol "public: __thiscall CTabRectangles::CTabRectangles(void)" (??0CTabRectangles@@QAE@XZ)
    Debug/Geometrie.exe : fatal error LNK1120: 2 unresolved externals
    Voici le code de mon fichier .h :
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
     
    #ifndef GEO_H
    #define GEO_H
     
    #include "chaine.h"
     
    class CRectangle //un rectangle
    {
     
    public:
    	CRectangle();										//Constructeur par défaut
    	~CRectangle();										//Destructeur
     
    	bool			DefinirNom(const char* UnNom);			//Modificateur du membre m_Nom
    	bool			DefinirLongueur(double UneLongueur);	//Modificateur du membre m_Longueur
    	bool			DefinirLargeur(double UneLargeur);		//Modificateur du membre m_Largeur
     
    	const char*		Nom() const;							//Accesseur du membre m_Nom (le this pointe sur un objet constant)
    	const double	Longueur() const;						//Accesseur du membre m_Longueur (le this pointe sur un objet constant)
    	const double	Largeur() const;						//Accesseur du membre m_Nom (le this pointe sur un objet constant)
     
     
    private:
    	CChaine			m_Nom;									//Membre contenant l'adresse d'une chaîne de caractères allouée dynamiquement et contenant le nom du rectangle (chaîne non vide)
    	double			m_Longueur;			
    	double			m_Largeur;
     
     
     
    };
     
    class CCercle //un cercle
    {
    public:
    	CCercle();											//Constructeur par défaut
    	~CCercle();											//Destructeur par défaut
     
    	bool			DefinirNom(const char* UnNom);			//Modificateur de m_Nom (pour le cercle)
    	bool			DefinirRayon(double UnRayon);			//Modificateur de m_Rayon
     
    	const char*		Nom() const;							//Accesseur du membre m_Nom (this pointe sur une constante)
    	const double	Rayon() const;							//Accesseur du membre m_Rayon (this pointe sur une constante)
     
    private:
    	CChaine			m_Nom;
    	double			m_Rayon;
     
    };
     
    class CTriangle //un triangle
    {
     
    public:
    	CTriangle();
    	~CTriangle();
     
    	bool			DefinirNom(const char* UnNom);
    	bool			DefinirBase(double UneBase);
    	bool			DefinirHauteur(double UneHauteur);
     
    	const			char* Nom() const;
    	const			double Base() const;
    	const			double Hauteur() const;
     
    private:
    	CChaine			m_Triangle;								//Membre contenant l'adresse d'une chaine de caractère allouée dynamiquement et contenant le nom du rectangle
    	double			m_Base;
    	double			m_Hauteur;
     
    };
     
    class CTabRectangles
    {
     
    public:
    	CTabRectangles();
    	~CTabRectangles();
     
    	bool			Charger(const char* NomFichier);
    	void			Vider();
     
    private:
    	long			m_Nombre;
    	CRectangle**	m_Tableau;
    };
     
     
    class CTabCercles
    {
     
    public:
    	CTabCercles();
    	~CTabCercles();
     
    	bool			Charger(const char* NomFichier);
    	void			Vider();
     
    private:
     
    	long			m_Nombre;
    	CCercle**		m_Tableau;
     
    };
     
    class CTabTriangles
    {
    public:
    	CTabTriangles();
    	~CTabTriangles();
     
    	bool			Charger(const char* NomFichier);
    	void			Vider();
     
    private:
    	long			m_Nombre;
    	CTriangle**	m_Tableau;
    };
     
    #endif//GEO_H
    et voici le code de mon fichier principal (main) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <BasicConsole.h>
    #include "geo.h"
    #include "chaine.h"
     
     
    int main()
    {
     
    	CTabRectangles	Rectangles;
     
    	return 0;
    }
    Merci d'avance pour votre aide et bon Dimanche.

    beegees

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Le compilateur te dis qu'il n'arrive pas à trouver la définition du constructeur ni du destructeur de CTabRectangles. Et comme tu ne nous montre qu'un .h, qui contient juste leur déclaration, on ne peut pas vérifier si tu les as bien définis.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Le compilateur te dis qu'il n'arrive pas à trouver la définition du constructeur ni du destructeur de CTabRectangles. Et comme tu ne nous montre qu'un .h, qui contient juste leur déclaration, on ne peut pas vérifier si tu les as bien définis.
    Salut,

    Merci pour ta réponse.

    Il faut donc déclarer le constructeur et le destructeur ?

    Je pensais que le constructeur par défaut et le destructeur par défaut ne devaient pas être définis.

    J'édite ici :

    Si je déclare un constructeur et un destructeur, je dois le définir ? sinon, je peux ne pas les déclarer (constructeur/Destructeur) et alors je ne dois pas le définir et les valeurs par défaut (0 pour le int par exemple) seront affectés alors ?

    Le problème doit se trouver là.

    Merci beaucoup pour ton aide (surtout un dimanche).

    beegees

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

    Informations professionnelles :
    Activité : aucun

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

    Selon toi, que font toutes les lignes de ton fichier d'en-tête (de ton fichier .h)

    As tu conscience que ce fichier n'a qu'une seule raison d'être: définir tes différentes classes et déclarer les membres et méthodes qu'elles contiennentr.

    Par définir, il faut comprendre que tu donne un contenu à tes différentes classes.
    Quant à la déclaration des méthodes, c'est comme si tu disais au compilateur
    Tu vas sans doute croiser un appel à l'une des méthodes qui appartiennent à la classe CRectangle...

    Cette méthode existe, mais ce sera à l'éditeur de liens de faire correspondre l'appel avec le code correspondant
    Seulement, voilà...


    Dans ta fonction principale "main", tu ne fais encore qu'une seule chose: tu demande la création d'une instance de ton objet de type CRectangle.

    Ce simple fait provoque l'appel du constructeur de la classe CRectangle (AKA la méthode publique qui a été déclarée sous le nom et la signature de CRectangle() ).

    Le compilateur "croit" que la méthode en question existe, et crée donc l'appel correspondant sans se poser de question (pour lui, il existe une implémentation de cette méthode )

    Mais, si tu n'a pas fourni un fichier d'implémentation dans lequel ces méthodes sont réellement implémentées (dans lequel tu indique ce que tu veux que ces méthodes fassent), le compilateur n'a pas pu créer le code binaire correspondant dans le fichier objet.

    Quand tu en arrive à l'étape de l'édition des liens, l'éditeur de liens va parcourir les différents fichiers objets créés par le compilateur et se rendre compte qu'à un moment, ce code fait appel au constructeur de la classe CRectangle.

    Il va donc chercher, dans les différents fichiers objet, l'implémentation de cette méthode afin de pouvoir faire correspondre l'appel de la méthode avec son implémentation.

    Or, si tu as satisfait le compilateur en lui disant que cette méthode existe, tu n'a fait que la moitié du chemin, car il ne vérifie pas que tu lui fournis bel et bien un implémentation de celle-ci, et, sans l'implémentation de la méthode, l'éditeur de lien ne peut pas faire son travail, et il se plaint

    L'erreur que tu obtiens, ce n'est que la plainte de l'éditeur de liens qui correspond, en gros à

    Tu as dit au compilateur que le constructeur existait, et il a travaillé avec cette certitude.
    Tu m'a dit que le constructeur existe, et j'ai un symbole (un équivalent) dans la liste des fonctions qui existent.

    Mais je ne trouve pas l'implémentation de cette fonction.

    Bref, tu n'es qu'un menteur, je boude ...
    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 éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Salut Koala,

    J'aprécie beaucoup ta réponse qui est assez pédagogique, merci.

    En effet, avec la réponse de Loic, j'ai compris mon erreur.

    Heureusement que j'ai indiqué que j'étais un débutant en C++ (pas en programmation).

    S'est super, je mets de côté ta réponse que je relierai sans doute dans un proche futur.

    Merci encore.

    beegees

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par beegees Voir le message

    Si je déclare un constructeur et un destructeur, je dois le définir ?
    Si une classe n'a déclaré aucun destructeur, un destructeur "vide"est généré.

    Si une classe n'a déclaré aucun constructeur, un constructeur par défaut "vide" est généré.

    Si une classe n'a déclaré aucun constructeur par copie, un constructeur par copie membre à membre est généré.

    Si une classe n'a déclaré aucun operator=, un operator= membre à membre est généré.

    Donc, oui, comme tu l'as déclaré, tu as inhibé la génération automatique, donc à toi de le définir.

    Citation Envoyé par beegees Voir le message
    sinon, je peux ne pas les déclarer (constructeur/Destructeur) et alors je ne dois pas le définir et les valeurs par défaut (0 pour le int par exemple) seront affectés alors ?
    Ta donnée membre serait une classe, elle serait effectivement crée avec son propre constructeur par défaut. Comme il s'agit d'un type de base, elle sera simplement non initialisée (personnellement, j'aurais préféré qu'elle soit initialisée par défaut, mais ça pourrait causer des baisses de performances, par exemple par rapport à une bête structure qu'on porterait de C vers C++, si on initialisait la structure dans son constructeur généré automatiquement).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Merci beacoup pour ta réponse.

    S'est une erreur que je ne commetrai plus.

    Merci pour tes explications très claires et très importantes.

    beegees

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

Discussions similaires

  1. [10.2][UNIX] Problème de groupe lors de la création de fichiers
    Par Escandil dans le forum Administration
    Réponses: 4
    Dernier message: 02/10/2009, 13h22
  2. Réponses: 2
    Dernier message: 09/09/2009, 11h40
  3. Problême d'accent lors de la création d'un fichier txt
    Par maxmarie dans le forum Windows Mobile
    Réponses: 15
    Dernier message: 24/08/2007, 21h59
  4. Problème de charset lors de la création d'une instance 8i
    Par girint dans le forum Administration
    Réponses: 2
    Dernier message: 15/06/2007, 13h50
  5. Réponses: 8
    Dernier message: 06/06/2007, 17h03

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