C++ et namespace

Motivations
Définition
Utilisation
Namespace sans nom
Alias
Using
Template
Conception et nommage

Retour en haut de la page...

Motivations

De nombreuses librairies utilisent des noms identiques, pour des objets qui ne le sont pas forcément, sémantiquement et structurellement (par exemple Object, Date ou encore String). Cela entraîne l'apparition de conflits de noms, et rend donc impossible l'utilisation de ces différentes librairies dans un même fichier.

Pour éviter cela, certaines librairies utilisent des préfixes (par exemple les MFC : CObject ou CString). Les conflits peuvent cependant persister dans le cas de préfixes réduits et/ou communs.

C'est donc pour éviter ces conflits que le C++ s'est doté " récemment " d'espaces de nommage ou namespace.

Retour en haut de la page...

 

Définition

Comme le package en UML, on peut donc regrouper des classes en namespace.

Mais contrairement à une définition de classe, un namespace peut être définit en plusieurs fois, séparément.
Règle :
Il est donc recommandé d'ouvrir un namespace pour déclarer une classe, afin de se prémunir d'une définition involontaire.

Tout ce qui peut être déclaré dans le scope global peut l'être dans un namespace: classe, structure, fonctions, variables, typedef.

Un namespace ressemble donc à une classe à deux différences près:

  1. Il n'y a pas de partie portion privée ou protégée, tout est public.
  2. Il peut être déclaré en plusieurs fois, dans plusieurs fichiers sources (Deux classes d'un même namespace peuvent être déclarée et définies dans deux fichiers séparés, c'est même recommandé.).

L'inclusion dans un namespace ne change pas le comportement. Cela ne fait que prévenir les conflits de nom en fournissant plus de souplesse dans le nommage (sur les plans fonctionnel et structurel) : on peut ainsi avoir deux objets différent qui portent le même nom car étant dans des namespaces différents. Pour celui qui appréhende un code en commençant par une des deux classes, lorsqu'il arrive sur la deuxième, il a déjà une idée !

Retour en haut de la page...

 

Utilisation

Pour accéder aux éléments d'un namespace, il faut utiliser l'opérateur de porté '::' (A ne pas confondre avec l'appel à une méthode statique).

Retour en haut de la page...

 

Namespace sans nom

Tout ce qui est dans namespace sans nom est privé au fichier courant.

Cela est recommandé pour des fonctions ou des constantes dont l'accès est reservé aux membres d'un fichier (méthodes d'une classe).

Exemple du fichier MonJoliBateau.cpp, de la classe du même nom :

#include "MonJoliBateau.h"

namespace
{
    const int gradeDuCapitaine(99);
	
    const long ageDuCapitaine(const int tailleDuBateau)
    {
        return tailleDuBateau * 2 + 1;
    }
}

MonJoliBateau::MonJoliBateau()
{
}

...

Retour en haut de la page...

 

Alias

Plus l'utilisation d'un namespace est importante,
plus la tentation d'en raccourcir le nom est grande,
plus le risque d'apparition de nouveaux conflits est élevé.

Deux solutions s'offrent alors :

L'alias apparaît vraiment justifié lorsque les niveaux de namespaces imbriqués sont nombreux, ou que les noms de namespace sont trop long.. Des noms trop longs peuvent cependant être le signe d'une conception imparfaite : une granularité plus fine peut raccourcir le nom des namespaces, mais en augmentant leur nombres ;o)

Attention de ne pas tomber en contradiction avec certaines règles de codage qui interdisent les abréviations.

Retour en haut de la page...

 

Using

Pas de using de namespace, car cela redescend tout le namespace. Le using de classe est préférable, mais cela peut poser problème en raison d'un autre bug du compilateur Microsoft Visual Studio :

Retour en haut de la page...

 

Template

...

Retour en haut de la page...

 

Conception et nommage

Le nom doit commencer par une majuscule comme les classes.

Ne pas mélanger des classes et des sous namespace dans un même namespace : un namespace ne contient soit que des sous-namespace, soit que des classes.

Il est souhaitable d'éviter des noms de projet, sauf éventuellement pour le namespace racine. Cela permet d'accroître la reutilisabilité du code.

L'arborescence de namespace doit respecter celle des répertoires qui doit elle même permettre d'appréhender facilement le code : éviter un namespace unique à la racine avec 20 sous-namespace dedans.

Lorsque l'on a plusieurs niveaux de namespace avec des classes, voire des classes imbriquées, il est important que le chemin complet (Namespace::SousNamespace::Classe::ClasseImbriquee) soit parlant et reste cohérent sans être redondant (Date::isValid et non Date::isValidDate).

Retour en haut de la page...

 

29/02/2004

www.2ia.net © 2001-2004