2010-01-18 8 views
3

J'ai un ensemble de fonctions qui fonctionnent sur un fichier. A l'origine je l'ai fait dans une classe, avec le seul membre privé étant un static const std::string qui était le nom du fichier. L'utilisateur a utilisé ces fonctions en créant un objet et en lui appelant des fonctions. Cependant, je pense que je vais passer à l'utilisation d'un espace de noms, car c'est juste un ensemble de fonctions et cela a plus de sens. Le seul problème est que je voudrais toujours garder cette chaîne constante. Est-ce que faire quelque chose dans ce sens serait bien?Fin d'avoir des variables dans un espace de noms?

namespace FileHandler { 
    // Functions to do stuff with file 
    const std::string FILE_NAME; 
} 

Je dispose d'un fichier de mise en œuvre distincte pour l'espace de noms, mais je me demande si la perte d'encapsulation d'avoir le nom de fichier soit un membre privé dans une classe est intéressant d'utiliser l'espace de noms à la place.

Répondre

5

Vous pouvez faire des choses similaires mais elles auront des sémantiques différentes.

Dans une classe, une variable statique est une déclaration, pas une définition, elle nécessite toujours une définition en dehors de la classe; une déclaration de variable dans un espace de noms est une définition sauf si vous marquez extern et ne fournissez pas d'initialiseur.

Dans votre cas, cela ne fait pas trop de différence car const variables ont une liaison interne par défaut, donc vous pouvez avoir plusieurs définitions dans un programme (une par unité de traduction) sans problèmes.

E.g.

class Test 
{ 
    static const std::string FILE_NAME; 
}; 

est (à certains égards) équivalent à:

namespace Test 
{ 
    extern const std::string FILE_NAME; 
} 

Si vous avez fait cela, vous déclarerait FILE_NAME comme une chaîne vide. Vous ne pouviez pas le redéclarer ailleurs dans la même unité de traduction.

namespace Test 
{ 
    const std::string FILE_NAME; 
} 

Vous pourriez, cependant, le faire.

namespace Test 
{ 
    const std::string FILE_NAME = "myfile.txt"; 
} 

Chaque unité de traduction aurait sa propre version de Test::FILE_NAME mais ils seraient tous en accord.

+0

Merci pour l'info. La raison pour laquelle je n'inclue pas la définition de la chaîne dans le fichier d'en-tête est qu'il n'est pas nécessaire que l'utilisateur sache, c'est pourquoi je le définis dans le fichier d'implémentation avec les fonctions dans l'espace de noms. – Anonymous

+0

Dans ce cas, vous pouvez faire 'extern const std :: string blah;' dans le fichier d'en-tête et 'const std :: string ns :: blah =" quel que soit ";' dans le fichier source. –

+0

Ai-je manqué quelque chose - pourquoi même déclarer ce nom de fichier dans l'en-tête, s'il était auparavant privé et que l'utilisateur n'a pas besoin de le savoir? Est-il utilisé dans un code en ligne dans l'en-tête, ou un paramètre de fonction par défaut, ou un tel? Sinon, déplacez-le entièrement dans le fichier d'implémentation. –

2

Je ne vois pas le problème qui vous a amené à passer d'une classe à l'utilisation d'un espace de noms. Si chaque fonction agit sur le fichier dont le nom est stocké dans FILE_NAME, alors le fichier semble être une partie parfaitement valide de l'état d'un objet. Passer de cela à ce qui équivaut à une variable globale est une forte odeur de code. Que se passe-t-il lorsque vous voulez effectuer des opérations sur deux fichiers à la fois? Que faire si vous voulez supporter différents types de fichiers? Il est beaucoup plus facile d'aborder ces questions avec une approche orientée objet qui évite l'état global. Si vous voulez vraiment utiliser "un ensemble de fonctions", alors vous pouvez considérer une approche plus fonctionnelle dans laquelle chaque fonction prend le nom du fichier (ou un pointeur de fichier) en tant que paramètre. De cette façon, les fonctions n'ont pas besoin d'accéder à l'état global.