102 votes

Méthode correcte pour définir les méthodes de l'espace de noms C++ dans le fichier .cpp

Probablement un doublon, mais pas facile à rechercher...

Avec un en-tête comme celui-ci :

namespace ns1
{
 class MyClass
 {
  void method();
 };
}

J'ai vu method() définis de plusieurs façons dans le fichier .cpp :

Version 1 :

namespace ns1
{
 void MyClass::method()
 {
  ...
 }
}

Version 2 :

using namespace ns1;

void MyClass::method()
{
 ...
}

Version 3 :

void ns1::MyClass::method()
{
 ...
}

Y a-t-il une "bonne" façon de procéder ? Certaines de ces expressions sont-elles "fausses" en ce sens qu'elles ne signifient pas toutes la même chose ?

49voto

KoinosOfMacedon Points 585

La version 2 n'est pas claire et n'est pas facile à comprendre car vous ne savez pas quel espace de nom MyClass appartient et c'est tout simplement illogique (la fonction de la classe n'est pas dans le même espace de noms ?)

La version 1 est correcte car elle montre que dans l'espace de noms, vous définissez la fonction.

La version 3 est correcte aussi parce que vous avez utilisé le :: l'opérateur de résolution de la portée pour faire référence à l MyClass::method () dans l'espace de noms ns1 . Je préfère la version 3.

Voir Espaces de noms (C++) . C'est la meilleure façon de procéder.

13voto

Dietmar Kühl Points 70604

J'utilise la version 4 (ci-dessous) parce qu'elle combine la plupart des avantages de la version 1 (fermeté de la définition résoactive) et de la version 3 (être le plus explicite possible). Le principal inconvénient est que les gens ne sont pas habitués à cette version, mais comme je la considère techniquement supérieure aux autres, cela ne me dérange pas.

Version 4 : utiliser la qualification complète en utilisant des alias d'espace de nom :

#include "my-header.hpp"
namespace OI = outer::inner;
void OI::Obj::method() {
    ...
}

Dans mon monde, j'utilise fréquemment des alias d'espaces de noms car tout est explicitement qualifié - à moins que ce ne soit pas possible (par exemple, les noms de variables) ou que ce soit un point de personnalisation connu (par exemple, swap() dans un modèle de fonction).

4voto

Paul Joireman Points 467

La version 3 rend l'association entre la classe et l'espace de nom très explicite, au prix d'une saisie plus importante. La version 1 évite cela mais capture l'association avec un bloc. La version 2 a tendance à cacher cette association et je l'éviterais.

3voto

justin Points 72871

Je choisis Num.3 (alias la version verbeuse). C'est plus de typage, mais l'intention est exacte pour vous et pour le compilateur. Le problème que vous avez affiché tel quel est en fait plus simple que le monde réel. Dans le monde réel, il y a d'autres portées pour les définitions, pas seulement les membres de la classe. Vos définitions ne sont pas très compliquées avec les classes uniquement - parce que leur portée n'est jamais rouverte (contrairement aux espaces de noms, à la portée globale, etc.).

Num.1 cela peut échouer avec des scopes autres que des classes - tout ce qui peut être rouvert. Ainsi, vous pouvez déclarer une nouvelle fonction dans un espace de nom en utilisant cette approche, ou vos inlines pourraient se retrouver substituées via ODR. Vous en aurez besoin pour certaines définitions (notamment les spécialisations de templates).

Num.2 C'est très fragile, en particulier dans les grandes bases de code - au fur et à mesure que les en-têtes et les dépendances changent, votre programme ne pourra pas être compilé.

Num.3 C'est l'idéal, mais c'est beaucoup à taper - ce que vous avez l'intention de définir quelque chose . C'est exactement ce qu'il fait, et le compilateur intervient pour s'assurer que vous n'avez pas fait d'erreur, qu'une définition n'est pas désynchronisée par rapport à sa déclaration, etc.

2voto

Renan Greinert Points 1252

Toutes les voies sont bonnes, et chacune a ses avantages et ses inconvénients.

Dans la version 1, vous avez l'avantage de ne pas avoir à écrire l'espace de nom devant chaque fonction. L'inconvénient est que vous obtiendrez une identification ennuyeuse, surtout si vous avez plus d'un niveau d'espaces de noms.

Dans la version 2, vous rendez votre code plus propre, mais si vous avez plus d'un espace de nom implémenté dans le CPP, l'un peut accéder directement aux fonctions et variables de l'autre, rendant votre espace de nom inutile (pour ce fichier cpp).

Dans la version 3, vous devrez taper davantage et vos lignes de fonction risquent d'être plus grandes que l'écran, ce qui est mauvais pour les effets de conception.

Il existe également une autre façon de l'utiliser. Elle est similaire à la première version, mais sans les problèmes d'identification.

C'est comme ça :

#define OPEN_NS1 namespace ns1 { 
#define CLOSE_NS1 }

OPEN_NS1

void MyClass::method()
{
...
}

CLOSE_NS1

C'est à vous de choisir celle qui convient le mieux à chaque situation =]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X