OVH Cloud OVH Cloud

namespaces et importation de classes/namespaces

47 réponses
Avatar
tibug
Bonjour,

[questions de débutant niveau pâquerettes :]

A mon niveau je vois juste les namespaces un peut comme des "librairies"
pour pouvoir organiser les objets et éviter les collisions (bon terme?).

fondamentalement je ne vois pas trop la différence entre utiliser un
namespace qui contiendrait un objet déclaré static et utiliser une
classe de type singleton ayant leur instance globale ...

les namespaces sont t'il chargés/déchargés quand il y en a
besoin/plus besoin ?

Est-ce que ça coûte plus cher en CPU/RAM d'utiliser un objet à
déclaré à l'interieur d'un namespace plutôt qu'à un objet du même
type déclaré en dehors ?

Sinon comment fait-on pour importer, dans un namespace A des classes
(implémentées dans d'autres fichiers) et faire en sorte que ces classes
ne puissent pas être visibles/utilisés directement ailleurs dans le code
(sans passer par le namespace N) ?
faut t'il obligatoirement en faire une librairie ?
(j'ai tenté des trucs vite fait avec extern mais ça ne compilait pas)

Pareil pour les namespaces, faut t'il obligatoirement quelque chose
comme :

//.h :
namespace A {
int MA();
namespace B { int MB(); }
}

//.cpp(s)
int A::mA() { return 1; }
int A::B::MB() { return 2; }


A+

tibug

10 réponses

1 2 3 4 5
Avatar
Fabien LE LEZ
On Fri, 18 Mar 2005 16:33:13 +0100, tibug <tibug29_AROBASE_yahoo_fr>:

A mon niveau je vois juste les namespaces un peut comme des "librairies"


J'imagine que tu veux parler des bibliothèques ?

pour pouvoir organiser les objets et éviter les collisions (bon terme?).


Justement, les bibliothèques ne sont pas vraiment efficaces contre ces
collisions. D'où l'utilité des namespaces : un namespace par
bibliothèque et tout va bien.

fondamentalement je ne vois pas trop la différence entre utiliser un
namespace qui contiendrait un objet déclaré static et utiliser une
classe de type singleton ayant leur instance globale ...


Il n'y a pas de notion d'instance d'un namespace comme la notion
d'instance d'une classe.
Mettre une fonction f() dans un namespace Machin, et écrire
Machin::f(), est juste une façon d'écrire Machin_f(). Avec quelques
fonctionnalités en plus ("using" notamment).

les namespaces sont t'il chargés/déchargés quand il y en a
besoin/plus besoin ?


Non.

Est-ce que ça coûte plus cher en CPU/RAM d'utiliser un objet à
déclaré à l'interieur d'un namespace plutôt qu'à un objet du même
type déclaré en dehors ?


Non. Le nom de la variable ou de la fonction est plus long, donc ça
peut avoir une influence (légère) sur la taille de l'exécutable si
cette information est conservée, mais c'est tout.

Pareil pour les namespaces, faut t'il obligatoirement quelque chose
comme :

//.h :
namespace A {
int MA();
namespace B { int MB(); }
}

//.cpp(s)
int A::mA() { return 1; }
int A::B::MB() { return 2; }


Non, cette écriture est plutôt rare (du moins, dans mon code).

On peut très bien écrire :

// x.h

namespace A
{
int foo();
}

// x.cpp

#include "x.h"
namespace A
{
int foo() { return 42; }
}

// y.h

namespace A
{
int bar (int n);
}

// y.cpp

#include "y.h"
#include "x.h"
namespace A
{
int bar (int n) { return foo() + 42; }
}



--
;-)

Avatar
tibug

On Fri, 18 Mar 2005 16:33:13 +0100, tibug <tibug29_AROBASE_yahoo_fr>:


A mon niveau je vois juste les namespaces un peut comme des "librairies"


J'imagine que tu veux parler des bibliothèques ?


arf... facheuse habitude avec ce faux ami .lib => [FR] "librairie" :-)

pour pouvoir organiser les objets et éviter les collisions (bon terme?).


Justement, les bibliothèques ne sont pas vraiment efficaces contre ces
collisions. D'où l'utilité des namespaces : un namespace par
bibliothèque et tout va bien.


c'est ce que je voulais dire, je vois un peu un namespace comme une
bibliothèques bien fichue qui n'entrerait pas en collision avec d'autres
en encapsulant ce qu'elle définit son propre espace de nommage.

Non, cette écriture est plutôt rare (du moins, dans mon code).

On peut très bien écrire :
[code pour namespace A déclaré plusieurs fois]


il ne m'était pas venu à l'idée que l'ou pouvait déclarer un namespace
à différents endroits; merci !


mon but ici (juste pour voir si c'est possible) est d'importer un
namespace Y à l'interieur d'un namespace X existant tout en déclarant
Y ailleurs (ses propres .h/.cpp)

le code suivant compile (edition de liens ok) seulement à condition
qu'on demande explicitement au compilateur (VC7.1) de d'abord compiler
'x.cpp'.

Il ne manquerait pas quelque chose (à part un makefile "fait main")
pour aider à la résolution des identificateurs ? :

Si on lui de demande de compiler juste 'y.cpp' (ce que je voudrais)
ou directement 'test.cpp' j'ai l'erreur :
error C2039: 'foo' : n'est pas membre de 'X::Y'


-- x.h ------------------

#ifndef NSX
#define NSX

#include "y.h"

namespace X {

int foo();
}
#endif // ifndef NAS


-- x.cpp ------------------ => compilation OK

#ifndef NSX
#include "x.h"
#endif

int X::foo() { return 1; }


-- y.h --------------------

#ifndef NSXY
#define NSXY

namespace X {
namespace Y { // à rajouter à X existant
int bar();
}
}
#endif // NSXY


-- y.cpp ------------------ => ne compile pas seul

#ifndef NSXY
#include "y.h"
#endif

int X::Y::foo() { return 2; }


-- test.cpp --------------- => ne compile pas "d'un trait"

#include "x.h"

int main() {
return X::foo() + X::Y::bar();
}

---------------------------

A+

tibug


Avatar
Fabien LE LEZ
On Fri, 18 Mar 2005 21:20:38 +0100, tibug <tibug29_AROBASE_yahoo_fr>:

-- x.h ------------------

#ifndef NSX
#define NSX


Si tu utilises des noms si courts pour ce genre de choses, tu vas te
faire avoir -- d'autant que l'API Win32, par exemple, est farcie de
#define.

-- x.cpp ------------------ => compilation OK

#ifndef NSX
#include "x.h"
#endif


Je ne vois pas l'intérêt du "#ifndef" ici -- ça alourdit le code, et
c'est inutile puisqu'il y a déjà un "#ifndef" au début du .h.


--
;-)

Avatar
Fabien LE LEZ
On Fri, 18 Mar 2005 21:20:38 +0100, tibug <tibug29_AROBASE_yahoo_fr>:

-- x.h ------------------

#ifndef NSX
#define NSX

#include "y.h"


Ce #include me paraît inutile, puisqu'on n'utilise dans x.h rien qui
ait été déclaré dans y.h.

Note que le code

namespace NS1
{
void foo();
}

namespace NS1
{
void bar();
}

est exactement équivalent à

namespace NS1
{
void bar();
}

namespace NS1
{
void foo();
}



--
;-)

Avatar
Fabien LE LEZ
On Fri, 18 Mar 2005 21:20:38 +0100, tibug <tibug29_AROBASE_yahoo_fr>:

error C2039: 'foo' : n'est pas membre de 'X::Y'


Ce qui est parfaitement exact. Dans tes .h, tu n'as déclaré qu'une
seule fonction dans X::Y : bar().

En passant, j'aime assez peu le mot "membre" ici : une fonction f()
est dans le namespace X (i.e. son "vrai" nom est "X::f()"), tout comme
sa définition est dans y.cpp ou que je suis dans mon appartement. Mais
bon, c'est du chipotage.


--
;-)

Avatar
tibug

On Fri, 18 Mar 2005 21:20:38 +0100, tibug <tibug29_AROBASE_yahoo_fr>:


error C2039: 'foo' : n'est pas membre de 'X::Y'


Ce qui est parfaitement exact. Dans tes .h, tu n'as déclaré qu'une
seule fonction dans X::Y : bar().


décidément, il faut que je réapprendre à lire :-(
et à me forcer à éviter les copier-coller...

il fallait évidement :

-- y.cpp ------------------
...
int X::Y::bar() { return 2; } // et non pas X::Y::foo()


-- x.h ------------------
#ifndef NSX
#define NSX


Si tu utilises des noms si courts pour ce genre de choses, tu vas te
faire avoir -- d'autant que l'API Win32, par exemple, est farcie de
#define.


oui, en général j'utilise quelque chose comme :

#ifndef MONPROG_MONENTETE_H
#define MONPROG_MONENTETE_H
...
#endif // MONPROG_MONENTETE_H

c'est vrai que les #ifndef sont alors redondants des les .cpp

merci

A+

tibug


Avatar
James Kanze
Fabien LE LEZ wrote:
On Fri, 18 Mar 2005 21:20:38 +0100, tibug <tibug29_AROBASE_yahoo_fr>:


-- x.h ------------------



#ifndef NSX
#define NSX



Si tu utilises des noms si courts pour ce genre de choses, tu
vas te faire avoir -- d'autant que l'API Win32, par exemple,
est farcie de #define.


Non seulement l'API Win32.

-- x.cpp ------------------ => compilation OK



#ifndef NSX
#include "x.h"
#endif



Je ne vois pas l'intérêt du "#ifndef" ici -- ça alourdit le
code, et c'est inutile puisqu'il y a déjà un "#ifndef" au
début du .h.


Ça peut jouer énormement sur les temps de compilation. Dans un
projet, l'ajoute des #ifndef autour de l'include a fait passer
le temps d'un build complète de 28 heures à 4 heures. Si
certains compilateurs, comme g++, détectent l'idiome des gardes de
l'inclusion, et évite de rouvrir le fichier un deuxième fois si
ce n'est pas nécessaire, ce n'est pas le cas de tous.

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


Avatar
Fabien LE LEZ
On Sat, 19 Mar 2005 17:47:06 +0100, James Kanze :

a fait passer
le temps d'un build complète de 28 heures à 4 heures


Un tel projet, c'est combien de fichiers / lignes de codes ?


--
;-)

Avatar
Jean-Marc Bourguet
James Kanze writes:

Je ne vois pas l'intérêt du "#ifndef" ici -- ça alourdit le
code, et c'est inutile puisqu'il y a déjà un "#ifndef" au
début du .h.


Ça peut jouer énormement sur les temps de compilation. Dans un
projet, l'ajoute des #ifndef autour de l'include a fait passer
le temps d'un build complète de 28 heures à 4 heures.


L'ajout de gardes externes dans les .cpp a divisé par 7 le
temps de compilation? J'ai des doutes. Je comprends que
les gardes externes dans les en-têtes peuvent éviter un
comportement quadratique, mais dans les .cpp je doute qu'ils
aient à eux seuls un effet aussi important.

Je viens d'aller voir, Laklos ne conseille les gardes
externes que dans les en-têtes, pas dans le code.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Michel Michaud
Dans le message ,
Je viens d'aller voir, Laklos ne conseille les gardes
externes que dans les en-têtes, pas dans le code.


Par contre, dans le (beaucoup plus récent) livre de Sutter et
Alexandrescu (C++ Coding Standards: 101 Rules, Guidelines,
and Best Practices) :

« Always write internal #include guards. Never write external
#include guards. »

Je n'ai pas encore le livre, alors je ne peux en dire plus. Mais
Lakos commence à être vieux...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/

1 2 3 4 5