Problème de linking lors de l'appel d'un .cpp
Bonjour tout le monde,
Je fais un premier exercice qui se passait bien jusqu'à il y'a 2 minutes.
J'obtiens un message d'erreur lors du linking :
Citation:
Linking...
Vehicule3.obj : error LNK2001: unresolved external symbol "private: static bool __cdecl CLeTout::FctnTraiterLigne(class CChargeurFichierTexte const &,void *)" (?FctnTraiterLigne@CLeTout@@CA_NABVCChargeurFichierTexte@@PAX@Z)
Debug/vehicule3.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
La ligne qui pose problème est celle-ci :
Code:
return Chargeur.Charger(NomFichier,'\t',CLeTout::FctnTraiterLigne,this);
car quand je fais "return true", tout se passe bien et je n'obtiens aucun message d'erreur lors de la compilation et du linking.
voici mon code : Merci d'avance pour votre aide.
beegees
Voici le fichier qui pose problème (où s'est peut être le chaine.h ou le chaine.cpp) :
Code:
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
| #include <BasicConsole.h>
#include "vehicule3.h"
#include "chaine.h"
Vehicule3::Vehicule3()
:NombreDePlace(0)
{
}
Vehicule3::~Vehicule3()
{
}
CVoiture::CVoiture()
:m_VTM(0.0)
{
}
CVoiture::~CVoiture()
{
}
CTabVoitures::CTabVoitures()
:m_Nombre(0),m_Tableau(NULL)
{
}
CTabVoitures::~CTabVoitures()
{
}
CLeTout::CLeTout()
{
}
CLeTout::~CLeTout()
{
}
bool CLeTout::Charger(const char* NomFichier)
{
CChargeurFichierTexte Chargeur;
return Chargeur.Charger(NomFichier,'\t',CLeTout::FctnTraiterLigne,this);
} |
voici le chaine.h :
Code:
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
| #ifndef CHAINE_H
#define CHAINE_H
class CChaine
{
public:
CChaine(); // Constructeur par défaut
CChaine(const CChaine& Source); // Constructeur par copie
CChaine(const char* UneChaine); // Constructeur spécifique
~CChaine(); // Destructeur
const char* Chaine() const; // Accesseur du texte de la chaîne
bool EstNull() const; // Accesseur de test sur le texte (m_Chaine == NULL)
bool EstVide() const; // Accesseur de test sur le texte (m_Chaine == NULL) || (m_Chaine == "")
void Vider(); // Modificateur permettant de supprimer le texte de la chaîne (on revient à NULL)
bool Chaine(const char* UneChaine); // Modificateur du texte de la chaîne
private:
char* m_Chaine; // Membre contenant l'adresse du tableau de caractères alloué dynamiquement
};
class CChaineComposee : private CChaine
{
public:
CChaineComposee(); // Constructeur par défaut
CChaineComposee(const CChaineComposee& Source); // Constructeur par copie
CChaineComposee(const char* UneChaine, char UnSeparateur); // Constructeur spécifique
~CChaineComposee(); // Destructeur
long NombreChamps() const; // Accesseur du nombre de champs
const char* Champs(long Indice) const; // Accesseur d'un champ
bool Definir(const char* UneChaine, char UnSeparateur); // Modificateur permettant de modifier la chaîne et de générer le tableau des champs
private:
bool Decomposer(char UnSeparateur); // Modificateur permettant de modifier la chaîne et de générer le tableau des champs
private:
long m_NbrChamps;
char** m_Champs;
};
////////////////////////////////
// Class CChargeurFichierTexte//
////////////////////////////////
class CChargeurFichierTexte : public CChaineComposee
/*Donc en fait cette classe CChargeurFichierTexte à un moment donné ce qu'elle va contenir
comme information se sont les données d'une ligne mais déjà décomposée, sont but s'est
d'arriver à lire une ligne du fichier texte et de la décomposer automatiquement et donc en
servant des fonctionnalités publiques de la classe et bien on aura la possibilité de savoir
ce qu'il y'avait comme information sur la ligne (le nombre de champs et les valeurs sous
forme de chaîne de caractère des différents champs) et ce qu'elle fournira en plus s'est
une méthode de chargement où on peut passer le nom du fichier et la fonction à appeler pour
pouvoir traiter les données d'une ligne puisque le but de la fonction charger s'est de :
- lire une ligne
- d'appeler la fonction passer par celui qui utilise cette classe là
- et ensuite d'exécuter cette fonction
- et ensuite de passer à la lecture de la ligne suivante et ce jusqu'à la fin du fichier.
*/
{
public:
CChargeurFichierTexte();
~CChargeurFichierTexte();
bool Charger(const char* NomFichier, char UnSeparateur, bool (* FctnTraiterLigne)(const CChargeurFichierTexte&, void*), void* Contexte);
private:
};
#endif//CHAINE_H |
et voici le chaine.cpp :
Code:
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
| #include <BasicConsole.h>
#include "chaine.h"
#include "chaine.h"
////////////////////
// Classe CChaine //
////////////////////
CChaine::CChaine() //constructeur par défaut
:m_Chaine(NULL)
{
}
CChaine::CChaine(const CChaine& Source) //constructeur par copie
:m_Chaine(NULL)
{
Chaine(Source.m_Chaine);
}
CChaine::CChaine(const char* UneChaine) //constructeur spécifique
:m_Chaine(NULL)
{
Chaine(UneChaine);
}
CChaine::~CChaine() //destructeur
{
Vider();
}
void CChaine::Vider()
{
if (m_Chaine != NULL)
{
free(m_Chaine);
m_Chaine = NULL;
}
}
bool CChaine::Chaine(const char* UneChaine)
{
if (UneChaine == NULL) return false;
void* Nouveau = realloc(m_Chaine,(strlen(UneChaine)+1)*sizeof(char));
if (Nouveau == NULL) return false;
m_Chaine = (char*)Nouveau;
strcpy(m_Chaine,UneChaine);
return true;
}
const char* CChaine::Chaine() const
{
return (m_Chaine != NULL) ? m_Chaine : "";
}
bool CChaine::EstNull() const
{
return (m_Chaine == NULL);
}
bool CChaine::EstVide() const
{
return (m_Chaine == NULL) || (m_Chaine[0] == 0);
}
////////////////////////////
// Classe CChaineComposee //
////////////////////////////
CChaineComposee::CChaineComposee()
:m_NbrChamps(0),m_Champs(NULL)
{
}
CChaineComposee::CChaineComposee(const CChaineComposee& Source)
:CChaine(Source),m_NbrChamps(0),m_Champs(NULL)
{
if (Source.m_NbrChamps > 0)
{
m_Champs = (char**)malloc(Source.m_NbrChamps*sizeof(char*));
if (m_Champs != NULL)
{
m_NbrChamps = Source.m_NbrChamps;
for (long n=0; n < Source.m_NbrChamps; n++)
{
long PosRel = Source.m_Champs[n] - Source.m_Champs[0];
m_Champs[n] = ((char*)Chaine()) + PosRel;
}
}
}
}
CChaineComposee::CChaineComposee(const char* UneChaine, char UnSeparateur)
:CChaine(UneChaine),m_NbrChamps(0),m_Champs(NULL)
{
Decomposer(UnSeparateur);
}
CChaineComposee::~CChaineComposee()
{
if (m_Champs) free(m_Champs);
}
long CChaineComposee::NombreChamps() const
{
return m_NbrChamps;
}
const char* CChaineComposee::Champs(long Indice) const
{
return ( (Indice >= 0) && (Indice < m_NbrChamps) ) ? m_Champs[Indice] : "";
}
bool CChaineComposee::Definir(const char* UneChaine, char UnSeparateur)
{
if (!Chaine(UneChaine)) return false;
return Decomposer(UnSeparateur);
}
bool CChaineComposee::Decomposer(char UnSeparateur)
{
m_NbrChamps = 0;
char* Texte = (char*)Chaine();
if (Texte == NULL) return false;
void* Nouveau = realloc(m_Champs,1*sizeof(char*));
if (Nouveau == NULL)
{
if (m_Champs)
{
free(m_Champs);
m_Champs = NULL;
}
return false;
}
m_Champs = (char**)Nouveau;
m_Champs[m_NbrChamps] = Texte;
m_NbrChamps++;
while (true)
{
char* Delimiteur = strchr(Texte,UnSeparateur);
if (Delimiteur == NULL) return true;
*Delimiteur = 0;
Texte = Delimiteur + 1;
void* Nouveau = realloc(m_Champs,(m_NbrChamps+1)*sizeof(char*));
if (Nouveau == NULL) return false;
m_Champs = (char**)Nouveau;
m_Champs[m_NbrChamps] = Texte;
m_NbrChamps++;
}
}
//////////////////////////////////
// Classe CChargeurFichierTexte //
//////////////////////////////////
CChargeurFichierTexte::CChargeurFichierTexte()
{
}
CChargeurFichierTexte::~CChargeurFichierTexte()
{
}
bool CChargeurFichierTexte::Charger(const char* NomFichier, char UnSeparateur, bool (* FctnTraiterLigne)(const CChargeurFichierTexte&, void*), void* Contexte)
{
const long TailleLigne = 500;
char Ligne[TailleLigne+1];
FILE* Fichier;
if ( (NomFichier == NULL) || (*NomFichier == 0) ) return false;
Fichier = fopen(NomFichier,"rt");
while (fgets(Ligne,TailleLigne,Fichier) != NULL)
{
long i = strlen(Ligne);
if ( (i > 0) && (Ligne[i-1] == '\n') ) Ligne[i-1] = 0;
if (Definir(Ligne,'\t'))
{
if (!FctnTraiterLigne(*this,Contexte))
{
fclose(Fichier);
return false;
}
}
}
fclose(Fichier);
return true;
} |
et pour être complet, voici le main :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <BasicConsole.h>
#include "vehicule3.h"
#include "chaine.h"
void main()
{
CLeTout LeTout;
if(LeTout.Charger("Vehicules.txt")) printf("ok");
} |
et le header :
Code:
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
| #include <BasicConsole.h>
#include "chaine.h"
class Vehicule3
{
public:
Vehicule3();
~Vehicule3();
short NombreDePlace;
private:
CChaine m_Nom;
CChaine m_Immatriculation;
};
class CVoiture : public Vehicule3
{
public:
CVoiture();
~CVoiture();
private:
double m_VTM; //Volume transportable de marchandise
};
class CTabVoitures
{
public:
CTabVoitures();
~CTabVoitures();
private:
long m_Nombre;
CVoiture** m_Tableau;
};
class CLeTout
{
public:
CLeTout();
~CLeTout();
bool Charger(const char* NomFichier);
private:
private:
static bool FctnTraiterLigne(const CChargeurFichierTexte& CC, void* Contexte);
bool TraiterLigne(const CChargeurFichierTexte& CC);
private:
CTabVoitures m_TV; //Tableau de voitures
}; |