OVH Cloud OVH Cloud

pb de namespace

9 réponses
Avatar
Marc
bonjour, quelqu'un peut-il me dire où est le pb dans le code suivant

// fichier mt_string.h

namespace mt_string {

std::string IntToString(const int&);
}

//fichier mt_string.cpp

#include <sstream>
#include "mt_string.h"
using namespace m_string;

std::string IntToString(const int &i)
{/*...*/ }

Mon pb, c'est que quand j'utilise m_string::IntToString dans d'autres
unités, l'éditeur de liens me signale que cette fonction n'existe pas. La
fonction IntToString a pourtant bien été déclarée dans l'espace de noms
m_string...
Alors, où est le pb ?

Si je qualifie explicitement IntToString dans le fichier cpp, ça marche. Où
est la différence ?

//fichier mt_string.cpp

#include <sstream>
#include "mt_string.h"
std::string mt_string::IntToString(const int &i) // avec qualification
complète du nom, c'est ok !
{/*...*/ }

Merci de votre aide

9 réponses

Avatar
Christophe de VIENNE
Marc wrote:
bonjour, quelqu'un peut-il me dire où est le pb dans le code suivant

// fichier mt_string.h

namespace mt_string {

std::string IntToString(const int&);
}

//fichier mt_string.cpp

#include <sstream>
#include "mt_string.h"
using namespace m_string;


using namespace mt_string;
^


std::string IntToString(const int &i)
{/*...*/ }




--
Christophe de Vienne

Avatar
Fabien LE LEZ
On Tue, 3 Aug 2004 14:25:52 +0200, "Marc" :

#include <sstream>
#include "mt_string.h"
using namespace m_string;


Ici, tu indiques au compilo d'aller chercher des fonctions dans le
namespace "m_string", si besoin est.

std::string IntToString(const int &i)


Là, tu définis une fonction en-dehors de tout namespace. En gros, tu
définis "::IntToString (int const&)", et du coup
"m_string::IntToString (int const&)" n'est jamais défini.

Il faudrait écrire :

namespace m_string
{
std::string IntToString(const int &i)
{...}
}//end namespace m_string

Note que la directive "using namespace;" casse partiellement l'utilité
du namespace, donc ne doit être mise qu'à la suite d'un choix
conscient, pas d'un automatisme.


--
;-)

Avatar
Andre Heinen
On Tue, 3 Aug 2004 14:25:52 +0200, "Marc"
wrote:

bonjour, quelqu'un peut-il me dire où est le pb dans le code suivant

// fichier mt_string.h

namespace mt_string {

std::string IntToString(const int&);


Ici, tu déclares mt_string::IntToString(const int&)

}

//fichier mt_string.cpp

#include <sstream>
#include "mt_string.h"
using namespace m_string;


Ceci signifie que si tu essaies d'*utiliser* (pas de définir) une
fonction, et que le compilateur ne la trouve pas dans ::, il ira
chercher dans m_string::. (Je suppose que tu as voulu dire
"mt_string", avec un t?)

std::string IntToString(const int &i)
{/*...*/ }


Ici, tu ne définis pas mt_string::IntToString(const int&). Au
lieu de ça, tu déclares et tu définis une fonction
::IntToString(const int&) (dans l'espace de noms global, donc).
Cette fonction n'a pas encore été déclarée, mais ce n'est pas
grave: la définition tient lieu de déclaration.

Mon pb, c'est que quand j'utilise m_string::IntToString dans d'autres
unités, l'éditeur de liens me signale que cette fonction n'existe pas.


Hé non. Tu ne l'as pas définie.

La
fonction IntToString a pourtant bien été déclarée dans l'espace de noms
m_string...


Déclarée, mais pas définie.

Alors, où est le pb ?

Si je qualifie explicitement IntToString dans le fichier cpp, ça marche. Où
est la différence ?

//fichier mt_string.cpp

#include <sstream>
#include "mt_string.h"
std::string mt_string::IntToString(const int &i) // avec qualification
complète du nom, c'est ok !
{/*...*/ }


Ceci est effectivement la bonne solution: il est maintenant clair
que tu définis non pas ::IntToString(const int&), mais
mt_string::IntToString(const int&).

Merci de votre aide


De rien. PS: comme un int est léger, passe-le plutôt par valeur:
mt_string::IntToString(int)

--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"

Avatar
drkm
Christophe de VIENNE writes:

Marc wrote:

bonjour, quelqu'un peut-il me dire où est le pb dans le code suivant
// fichier mt_string.h
namespace mt_string {
std::string IntToString(const int&);
}
//fichier mt_string.cpp
#include <sstream>
#include "mt_string.h"
using namespace m_string;


using namespace mt_string;

std::string IntToString(const int &i)
{/*...*/ }



Ce qui ne devrait pas changer grand-chose à son problème. Il
définit (et déclare au passage) une fonction nommée `::IntToString()'.
Il doit effectivement indiquer l'appartenance à `mt_string', la clause
`using' ne change rien dans ce cas.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html


Avatar
Andre Heinen
On Tue, 03 Aug 2004 14:40:45 +0200, Fabien LE LEZ
wrote:

Il faudrait écrire :

namespace m_string
{
std::string IntToString(const int &i)
{...}
}//end namespace m_string


Ca marche, mais ce n'est pas l'idéal. Soit par exemple le petit
programme suivant:

#include <string>

namespace mt_string {
std::string IntToString(const int&);
}

namespace mt_string {
std::string InToString(const int &i) {
// ^ faute de frappe
return std::string();
}
}

int main() {
}

On se retrouve avec une fonction IntToString déclarée mais pas
définie, et une fonction InToString déclarée et définie. Le
compilateur ne trouvera pas l'erreur. Bien sûr, si on tente
d'utiliser la fonction, l'éditeur de liens détectera l'erreur,
mais sera incapable de signaler à quel endroit du fichier source
elle s'est produite.

Il vaut mieux que Marc utilise la solution qu'il a lui-même
trouvée:

#include <string>

namespace mt_string {
std::string IntToString(const int&);
}

std::string mt_string::InToString(const int &i) {
// ^ faute de frappe
return std::string();
}

int main() {
}

En dehors d'une directive namespace, il est interdit de définir
une fonction qui n'a pas été préalablement déclarée. Avec cette
solution-ci, l'erreur est détectée dès la compilation, et on
reçoit un message d'erreur explicite.

Voir Stroustrup 8.2.

--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"

Avatar
drkm
Andre Heinen writes:

Il vaut mieux que Marc utilise la solution qu'il a lui-même
trouvée:

#include <string>

namespace mt_string {
std::string IntToString(const int&);
}

std::string mt_string::InToString(const int &i) {
// ^ faute de frappe
return std::string();
}

int main() {
}


La solution consiste à faire une faute de frappe ?-)

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Avatar
Andre Heinen
On Tue, 03 Aug 2004 15:30:03 +0200, drkm
wrote:

La solution consiste à faire une faute de frappe ?-)


Fin de journée? On est fatigué?
;-)

--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"

Avatar
Fabien LE LEZ
On Tue, 03 Aug 2004 15:19:32 +0200, Andre Heinen
:

Ca marche, mais ce n'est pas l'idéal.


Franchement, si. Ta solution répond à un problème dont AMHA tu
sur-évalues l'importance. Je n'ai jamais eu de problème sérieux lié à
une telle faute de frappe (mais peut-être est-ce parce que j'ai la
chance d'utiliser un éditeur qui supporte le copier-coller).

De plus, ta solution est encore gérable quand un namespace ne contient
qu'une fonction. Dès qu'il contient un bon paquet de fonctions et de
classes (en bref, dès que le besoin d'un namespace se fait sentir), je
préfère englober tout le .h et le .cpp dans un "namespace xx { ... }".

Ainsi, le .h et le .cpp ont tous les deux la forme suivante :

#includes et forward-declarations éventuelles de classes
namespace machin {
le code
}//end namespace machin


Note : il m'arrive assez rarement d'avoir des modules qui mélangent
des namespaces non-anonymes.


--
;-)

Avatar
Andre Heinen
On Tue, 03 Aug 2004 21:55:33 +0200, Fabien LE LEZ
wrote:

Je n'ai jamais eu de problème sérieux lié à
une telle faute de frappe (mais peut-être est-ce parce que j'ai la
chance d'utiliser un éditeur qui supporte le copier-coller).


Tu n'as pas tort, il faudra que j'upgrade...
;-)

--
Andre Heinen
My address is "a dot heinen at europeanlink dot com"