View
105
Download
1
Category
Preview:
Citation preview
Structures de donnéesIFT-2000
Abder AlikacemAbder Alikacem
Espace de nommage
Département d’informatique et de génie logiciel
Édition Septembre 2009
Département d’informatique et de génie logiciel
Plan
• Espace de nommage• Utilisation• Implémentation• Using namespace
Problème de collisions de noms…
• Qu’arrive-t-il si 2 fonctions globales différentes ont le même prototype ?
// MaLib1.hint f();
// MaLib2.hint f();class A{};
#include "MaLib1.h"#include "MaLib2.h"
int g(){ return 5 + f();//Quel f() ?}
Solution: créer des namespaces
• Namespace : • regroupement logique de fonctions, de classes, etc.• Possibilité de lui donner un nom:
NomDuNamespace::NomDeLEntite • Pas d'ambiguïté
// MaLib1.hnamespace Util{ int f();}
#include "MaLib1.h"#include "MaLib2.h"
int g(){ Tp1::A a; return 5 + Util::f(); // Ah, ok }
// MaLib2.hnamespace Tp1{ int f(); class A{};}
On se sert de l'opérateur d'appartenance ::
Using namespace
• namespace directement accessible :commande using
#include "MaLib1.h"#include "MaLib2.h"
using namespace Tp1;
int h(){ A a; int x = f(); return x + Util::f();}
Par le using, c'est Tp1::f().
Encapsulation: espace de nommage
namespace permet donc de définir un espace de nommage, i.e. un module (un paquetage en Java).
Exemple. Spécification
namespace pileDeChar { // interface dans un fichier Pile.hvoid empiler( char ) ;char depiler() ;bool estVide() ;
}
Encapsulation: espace de nommage
Exemple. Utilisation
Un fichier Test-pile.cpp peut alors utiliser l’interface :
#include "pile.h"#include <iostream>
int main() {pileDeChar::empiler( ’x’ ) ;if (pileDeChar::depiler() != ’x’) std::cerr << "impossible\n." ;
}
Rappel: le préfixe pileDeChar:: indique que empiler() et depiler() sont ceux du module pileDeChar.
Encapsulation: espace de nommage
Exemple. Implémentation
L’implémentation peut être donnée lors de la spécification (dans le fichier Pile.h) :
namespace pileDeChar {const int tailleMax = 200 ;char laPile [ tailleMax ] ;int sommet = 0 ;void empiler ( char c ) {
//Attention, pas de contrôle de débordementlaPile[ sommet ] = c ;++sommet ;
}char depiler() {// Attention, pas de contrôle de débordement
return laPile[ --sommet ] ;}bool estVide() {return sommet == 0 ;}
}
Encapsulation: espace de nommage
Exemple. Implémentation
Il est possible de donner l’implémentation d’une fonction séparément (ici dans Pile.cpp), en préfixant le nom de la fonction par l’identificateur de son espace de nommage :
#include "Pile.h"namespace pileDeChar {
const int tailleMax = 200 ;char laPile [ tailleMax ] ;int sommet = 0 ;
}
int pile_de_char::depiler() {// contrôle de débordement...return pileDeChar::laPile[ --sommet ] ;
}
void pileDeChar::empiler ( char c ) { ... } ;bool pileDeChar::estVide ( ) { ... } ;
Encapsulation: espace de nommage
Exemple. Bon usage du namespace
Il est possible de spécifier que tous les noms doivent également être cherchés dans un namespace donné. Le préfixage par pileDeChar:: peut alors être omis si il n’y a pas d’ambiguïté.
int main() {pileDeChar::empiler(’a’);using namespace pileDeChar;depiler();
return 0;}
Bon usage du using
• Inutile de mettre des using pour chacun des namespaces disponibles : • l'ambiguïté revient.
• Un using peut-être local :
• Ne jamais utiliser de using dans un .h :
• tous les fichiers qui l'incluront seront pollués.
// Quelque part { using namespace Util; // Util est accessible directement dans ce bloc }
Bon usage du using
#include "MaLib1.h"#include "MaLib2.h"#include <string>
namespace util{
class B{public :
std::string afficher();private:
Tp1::A a;std::string tmp;
};} // --- namespace utilstd::string afficher(){
using namespace std;string s;// traitement à fairereturn s;
}
On peut rajouter quelque chose dans un namespace déjà défini ailleurs.
Ce using n'affecte que le corps de cette fonction.
Encapsulation: espace de nommage
Koenig lookup
Une fonctionnalité intéressante des espaces de nommage est le “Koenig lookup” :
lors d’un appel à une fonction le type des arguments permet parfois de lever l’ambiguïté. Ceci peut être très utile pour faire des fonctions génériques modifiables par la suite (puisque un namespace est une structure ouverte à laquelle il est toujours possible d’ajouter des données ou des méthodes).
Encapsulation: espace de nommage
Koenig lookup
Exemple
#include <iostream>#include <list>#include <vector>namespace Listes {struct TypeDeDonnees { std::list<int> valeurs; };void affiche(TypeDeDonnees l) { std::cout << "Listes\n"; }}namespace Vecteurs {struct TypeDeDonnees { std::vector<int> valeurs; };void affiche(TypeDeDonnees l) { std::cout << "Vecteurs\n"; }}int main() {Vecteurs::TypeDeDonnees v;// Vecteurs::affiche est trouvée, même sans ‘‘using’’,// grâce à son paramètre de type Vecteurs::TypeDeDonnees.affiche( v ) ;return 0;}
Namespace et librairie standard
librairie standard en C++ :dans le namespace std :• Fonctions I/O ( console, fichiers, ... )• Classes de base ( string, iterator, ... )• Conteneurs ( vector, list, ... )• Algorithmes standardisés ( tri, recherche, …)
souvent la commande using namespace std; dans les fichiers .cpp .
Recommended