Probablement un doublon, mais pas facile à rechercher ...
Étant donné un en-tête comme:
namespace ns1
{
class MyClass
{
void method();
};
}
J'ai vu method()
défini de plusieurs manières 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 le faire? Est-ce que certains de ces éléments sont «faux» en ce sens qu'ils ne signifient pas tous la même chose?
c++
coding-style
namespaces
Monsieur Boy
la source
la source
Réponses:
La version 2 n'est pas claire et pas facile à comprendre car vous ne savez pas à quel espace de noms
MyClass
appartient et c'est juste illogique (la fonction de classe n'est pas dans le même espace de noms?)La version 1 a raison car elle montre que dans l'espace de noms, vous définissez la fonction.
La version 3 a raison également parce que vous avez utilisé l'
::
opérateur de résolution d'étendue pour faire référence àMyClass::method ()
dans l'espace de nomsns1
. Je préfère la version 3.Voir Espaces de noms (C ++) . C'est la meilleure façon de procéder.
la source
namespace N {struct X { void f(); }; X operator==( X const &, X const & ); }
, maintenant dans le fichier cpp avec l' instruction using , vous pouvez définir la fonction membre commevoid X::f() {}
, mais si vous définissezX operator==(X const&, X const&)
vous définirez un opérateur différent de celui défini dans l'en-tête (vous devrez utiliser 1 ou 3 pour la fonction libre).5 ans plus tard et j'ai pensé que je mentionnerais ceci, qui à la fois est joli et n'est pas mal
la source
J'utilise la version 4 (ci-dessous) car elle combine la plupart des avantages de la version 1 (lacune de la définition résoective) et de la version 3 (être au maximum explicite). Le principal inconvénient est que les gens n'y sont pas habitués, mais comme je le considère techniquement supérieur aux alternatives, cela ne me dérange pas.
Version 4: utilisez la qualification complète à l'aide d'alias d'espace de noms:
Dans mon monde, j'utilise fréquemment des alias d'espace de noms car tout est explicitement qualifié - à moins que cela ne puisse pas (par exemple les noms de variables) ou qu'il s'agisse d'un point de personnalisation connu (par exemple swap () dans un modèle de fonction).
la source
outer
et sont-ils déjàinner
définis comme des espaces de noms dans d'autres fichiers d'en-tête?La version 3 rend très explicite l'association entre la classe et l'espace de noms au détriment de plus de frappe. La version 1 évite cela mais capture l'association avec un bloc. La version 2 a tendance à cacher cela, donc j'éviterais celle-là.
la source
Googles C ++ Style Guide dicte votre version 1, sans indentation cependant.
la source
Je choisis Num.3 (aka la version verbeuse). C'est plus typé, mais l'intention est exacte pour vous et pour le compilateur. Le problème que vous avez publié tel quel est en fait plus simple que le monde réel. Dans le monde réel, il existe d'autres portées pour les définitions, pas seulement les membres de classe. Vos définitions ne sont pas très compliquées avec les classes uniquement - car leur portée n'est jamais rouverte (contrairement aux espaces de noms, à la portée globale, etc.).
Num.1 cela peut échouer avec des portées autres que des classes - tout ce qui peut être rouvert. Ainsi, vous pouvez déclarer une nouvelle fonction dans un espace de noms en utilisant cette approche, ou vos inlines pourraient finir par être remplacées via ODR. Vous en aurez besoin pour certaines définitions (notamment, les spécialisations de modèles).
Num.2 Ceci est très fragile, en particulier dans les grandes bases de code - à mesure que les en-têtes et les dépendances changent, votre programme échouera à se compiler.
Num.3 C'est idéal, mais beaucoup à taper - ce que votre intention est de définir quelque chose . C'est exactement cela, 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 avec sa déclaration, etc.
la source
Il s'avère que ce n'est pas seulement "une question de style de codage". Num. 2 conduit à une erreur de liaison lors de la définition et de l'initialisation d'une variable déclarée extern dans le fichier d'en-tête. Jetez un œil à l'exemple dans ma question. Définition de la constante dans l'espace de noms dans le fichier cpp
la source
Tous les moyens sont bons et chacun a ses avantages et ses inconvénients.
Dans la version 1, vous avez l'avantage de ne pas avoir à écrire l'espace de noms 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 noms en cours d'implémentation dans le CPP, l'un peut accéder directement aux fonctions et variables de l'autre, rendant votre espace de noms inutile (pour ce fichier cpp).
Dans la version 3, vous devrez taper plus et vos lignes de fonctions peuvent être plus grandes que l'écran, ce qui est mauvais pour les effets de conception.
Il y a aussi une autre façon dont certaines personnes l'utilisent. Il est similaire à la première version, mais sans les problèmes d'identification.
C'est comme ça:
A vous de choisir lequel est le meilleur pour chaque situation =]
la source
#ifdef
clause.#define OPEN_NS(X)
je pense que c'est un peu utile, mais pas vraiment ... Je ne m'oppose pas aux macros mais cela semble un peu OTT. Je pense que l'approche de Dietmar Kühl est meilleure pour les espaces de noms imbriqués.