OVH Cloud OVH Cloud

utilisation de string

10 réponses
Avatar
Laurent B
bonjour j'ai un petit pb avec STRING.
voila mon .h :


#ifndef _LISTECONTACT_
#define _LISTECONTACT_
#include "contact.h"
#include <string>


using namespace std;

class ListeContact {

private:
Contact * Pt_debut;

public:
void CreerListe (Contact *debut);
void SupprimerListe(ListeContact uneListe);
void AjouterContact (Contact unContact) ;
void ModifierContact(Contact *unContact);
void SupprimerContact();
void TrierContact();
void recherche(string c_nom,string c_prenom,string c_cp,string
c_ville,string c_tel,string c_fonction);
};


#endif /* _LISDTECONTACT_ */


voila mon .cpp :

#include "stdio.h"
#include <stdlib.h>
#include <string>
#include <iostream>
#include "listecontact.h"
#include "contact.h"



using namespace std;

...

void recherche(string c_nom,string c_prenom,string c_cp,string
c_ville,string c_tel,string c_fonction)
{
cout << " bonjour";
system("PAUSE");
}
;

#include "contact.h"
#include "listecontact.h"
#include <iostream>
#include <string>


void main ()
{
ListeContact l ;
l.recherche("e","e","e","e","e","e");
cout << "bonjour";
cout << endl ;
system ("PAUSE");
}



qd je lance g 2 pb :

--------------------Configuration: carnet - Win32 Debug--------------------
Compiling...
test.cpp
Linking...
test.obj : error LNK2001: unresolved external symbol "public: void
__thiscall ListeContact::recherche(class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,
class std::allocator<char> >,class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >,class std::basic_string<char,struct std::cha
r_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >)"
(?recherche@ListeContact@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@00000@Z)
Debug/carnet.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.

carnet.exe - 2 error(s), 0 warning(s)


Donc voila, vous ne pensez quoi ? ca peut venir d'ou ?

Laurent

10 réponses

Avatar
fabrizio
void recherche(string c_nom,string c_prenom,string c_cp,string
c_ville,string c_tel,string c_fonction)


non non non :)
void ListeContact::recherche(string c_nom, ...

comme tu l'avais fait recherche était défini dans l'espace de nom std.
donc quand tu fais :
l.recherche il ne trouve effectivement pas de fonction de ce nom.

Avatar
Stanislas RENAN
Bonjour,


void recherche(string c_nom,string c_prenom,string c_cp,string
c_ville,string c_tel,string c_fonction)



non non non :)
void ListeContact::recherche(string c_nom, ...

comme tu l'avais fait recherche était défini dans l'espace de nom std.
"using namespace std;" ?


Pour moi, comme il n'a pas défini de namespace englobant, il est au
niveau le plus élevé (global), et définit donc ::recherche() et non pas
std::recherche().

la directive using permet d'importer les noms, et ne déplace pas le
code des lignes suivant ladite directive dans le contexte en paramètre
de la directive.

namespace std
{
void recherche() {}
}

Je ne sais pas si on a le droit d'étendre ce namespace std sans
encourir la colère divine du grand normalisateur :)
--
Stanislas RENAN


Avatar
kanze
Laurent B wrote:
bonjour j'ai un petit pb avec STRING.


Pas avec std::string, mais avec quelque conceptes de base du
C++. Il y a aussi des détails que je me permettrais à signaler.

voila mon .h :

#ifndef _LISTECONTACT_
#define _LISTECONTACT_


Des noms qui commence par un _, suivi d'une majuscule, sont
réservés à l'implémentation. Tu n'as pas droit à les définir.

#include "contact.h"
#include <string>

using namespace std;


C'est en général pas un très bonne idée de faire un « using
namespace » à la portée globale dans un en-tête. Si vraiment tu
y tiens, mets-le dans la classe. (Personnellement, en ce qui me
concerne, le nom de la classe est std::string ; c'est donc comme
ça que je l'écris. Mais les avis sont partagés sur cette
politique, tandis que tous les expertes, je crois, s'accorde
pour condamner le « using namespace » à la portée globale dans
un en-tête.)

class ListeContact {

private:
Contact * Pt_debut;

public:
void CreerListe (Contact *debut);
void SupprimerListe(ListeContact uneListe);
void AjouterContact (Contact unContact) ;
void ModifierContact(Contact *unContact);
void SupprimerContact();
void TrierContact();
void recherche(string c_nom,string c_prenom,string c_cp,string
c_ville,string c_tel,string c_fonction);


Tu déclares ici une fonction membre de ListeContacte.

};

#endif /* _LISDTECONTACT_ */

voila mon .cpp :

#include "stdio.h"
#include <stdlib.h>
#include <string>
#include <iostream>
#include "listecontact.h"
#include "contact.h"

using namespace std;

...

void recherche(string c_nom,string c_prenom,string c_cp,string


Et ici, tu définis une fonction libre du nom recherche. Ce n'est
pas du tout la fonction que tu as déclarée.

Sans doute, ce que tu veux, c'est :

! void ListeContact::recherche...

c_ville,string c_tel,string c_fonction)
{
cout << " bonjour";
system("PAUSE");
}
;


Ici, c'est encore un troisième fichier (aussi un .cpp) je suppose.

#include "contact.h"
#include "listecontact.h"
#include <iostream>
#include <string>


void main ()


Formellement, c'est « int main() ». Certaines implémentations
permettent « void main() » comme une extention, mais d'autres
non. Toutes acceptent « int main() ».

{
ListeContact l ;
l.recherche("e","e","e","e","e","e");


Ici, tu appelles ListeContact::recherche. La fonction que tu
n'as pas défini.

cout << "bonjour";
cout << endl ;
system ("PAUSE");
}

qd je lance g 2 pb :

--------------------Configuration: carnet - Win32
Debug--------------------

Compiling...
test.cpp
Linking...
test.obj : error LNK2001: unresolved external symbol "public: void
__thiscall ListeContact::recherche(class
std::basic_string<char,struct

std::char_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,
class std::allocator<char> >,class std::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >,class std::basic_string<char,struct std::cha
r_traits<char>,class std::allocator<char> >,class
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >)"

(?@@QAEXV?$?$@std@@V?$all @2@@std@@)

Debug/carnet.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.


Et ce message d'erreur n'est pas assez clair ? L'externe non
résolu, c'est bien ListeContact::recherche. Et tu n'as nulle
part une définition d'une fonction de ce nom.

Ceci dit, si tu ne sais pas encore définir des fonctions membre,
je te conseille un bon livre ou un cour de C++ avant d'aller
plus loin. Parce qu'il s'agit vraiment d'un des b a ba de C++.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
fabrizio wrote:
void recherche(string c_nom,string c_prenom,string
c_cp,string c_ville,string c_tel,string c_fonction)


non non non :)
void ListeContact::recherche(string c_nom, ...

comme tu l'avais fait recherche était défini dans l'espace de
nom std. donc quand tu fais : l.recherche il ne trouve
effectivement pas de fonction de ce nom.


Ne confondons pas les choses. D'abord, comme il l'a écrit, il a
déclaré une fonction membre ::ListeContact::recherche, mais il a
défini une fonction libre ::recherche. Toutes les deux dans la
portée globale, c-à-d l'espace référentiel ::. Une fonction
membre n'est pas une fonction libre, une classe n'est pas un
espace référentiel, et il n'a rien défini ni déclaré dans
l'espace référentiel std (ce qui serait illégal, à quelques
menus exceptions près).

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
kanze
Stanislas RENAN wrote:

Je ne sais pas si on a le droit d'étendre ce namespace std
sans encourir la colère divine du grand normalisateur :)


C'est selon. Il y a quelques cas particuliers où c'est permis ;
la spécialisation d'une classe templatée standard sur un type
défini par l'utilisateur me vient à l'esprit, mais pour les
non-experts, la formulation simple de la règle est que c'est
interdit.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
drkm
writes:

il n'a rien défini ni déclaré dans
l'espace référentiel std (ce qui serait illégal, à quelques
menus exceptions près).


Je pensais que la seule chose permise était la spécialisation de
modèles de std:: sur des types utilisateurs. À quoi penses-tu ?

--drkm

Avatar
Falk Tannhäuser
wrote:

Stanislas RENAN wrote:
Je ne sais pas si on a le droit d'étendre ce namespace std
sans encourir la colère divine du grand normalisateur :)


C'est selon. Il y a quelques cas particuliers où c'est permis ;
la spécialisation d'une classe templatée standard sur un type
défini par l'utilisateur me vient à l'esprit


Si je comprends bien § 17.4.3.1/1, "A program may add template
specializations for any standard library template to namespace
std ...", cette spécialisation est aussi permise pour les
fonctions templatées sous certaines conditions - par exemple,
on devrait pouvoir faire ceci :

class MaClasse
{
...
public:
void swap(MaClasse&);
};

namespace std
{
template<> void swap(MaClasse& a, MaClasse& b)
{ a.swap(b); }
}

ce qui permet d'appeler le bon swap() lorsqu'on instancie
un template faisant appel à std::swap() avec MaClasse.

Falk


Avatar
kanze
Falk Tannhäuser wrote:
wrote:

Stanislas RENAN wrote:
Je ne sais pas si on a le droit d'étendre ce namespace std
sans encourir la colère divine du grand normalisateur :)


C'est selon. Il y a quelques cas particuliers où c'est
permis ; la spécialisation d'une classe templatée standard
sur un type défini par l'utilisateur me vient à l'esprit


Si je comprends bien § 17.4.3.1/1, "A program may add template
specializations for any standard library template to namespace
std ...", cette spécialisation est aussi permise pour les
fonctions templatées sous certaines conditions


Toute à fait. Je ne cherchais pas à être exhaustif, ni même très
précis ; j'ai juste cité la première chose qui m'est venu à
l'esprit.

- par exemple, on devrait pouvoir faire ceci :

class MaClasse
{
...
public:
void swap(MaClasse&);
};

namespace std
{
template<> void swap(MaClasse& a, MaClasse& b)
{ a.swap(b); }
}

ce qui permet d'appeler le bon swap() lorsqu'on instancie un
template faisant appel à std::swap() avec MaClasse.


Je dirais que c'est probablement le cas le plus courant où on
serait amené à définir quelque chose soi-même dans std.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34



Avatar
kanze
drkm wrote:
writes:

il n'a rien défini ni déclaré dans
l'espace référentiel std (ce qui serait illégal, à quelques
menus exceptions près).


Je pensais que la seule chose permise était la
spécialisation de modèles de std:: sur des types utilisateurs.
À quoi penses-tu ?


C'est à ça, précisement, que je pensais. Mais je ne me mettrai
pas la main au feu qu'il n'y a pas d'autre exception cachée
quelque part dans un coin.

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
drkm
writes:

Mais je ne me mettrai
pas la main au feu qu'il n'y a pas d'autre exception cachée
quelque part dans un coin.


C'est rarement une bonne idée lorsque l'on parle de la norme.

--drkm