Disons que j'ai ou vais écrire un ensemble de fonctions connexes. Disons qu'ils sont liés aux mathématiques. Sur le plan organisationnel, dois-je:
- Écrire ces fonctions et les mettre dans mon
MyMath
espace de noms et y faire référence viaMyMath::XYZ()
- Créez une classe appelée
MyMath
et rendez ces méthodes statiques et reportez-vous de la même manièreMyMath::XYZ()
Pourquoi devrais-je choisir l'un plutôt que l'autre pour organiser mon logiciel?
c++
namespaces
static-methods
RobertL
la source
la source
Réponses:
Par défaut, utilisez les fonctions d'espaces de noms.
Les classes doivent créer des objets et non remplacer des espaces de noms.
En code orienté objet
Scott Meyers a écrit un article entier pour son livre Effective C ++ sur ce sujet, "Préférez les fonctions non-membres non-amis aux fonctions membres". J'ai trouvé une référence en ligne à ce principe dans un article de Herb Sutter:http://www.gotw.ca/gotw/084.htm
La chose importante à savoir est la suivante: En C ++, les fonctions du même espace de noms qu'une classe appartiennent à l'interface de cette classe (car ADL recherchera ces fonctions lors de la résolution des appels de fonction).
Les fonctions à espace de nom, sauf si elles sont déclarées «ami», n'ont pas accès aux internes de la classe, contrairement aux méthodes statiques.
Cela signifie, par exemple, que lors de la maintenance de votre classe, si vous devez modifier les internes de votre classe, vous devrez rechercher des effets secondaires dans toutes ses méthodes, y compris les effets statiques.
Extension I
Ajout de code à l'interface d'une classe.
En C #, vous pouvez ajouter des méthodes à une classe même si vous n'y avez pas accès. Mais en C ++, c'est impossible.
Mais, toujours en C ++, vous pouvez toujours ajouter une fonction d'espacement de noms, même à une classe que quelqu'un a écrite pour vous.
Voyez de l'autre côté, cela est important lors de la conception de votre code, car en plaçant vos fonctions dans un espace de noms, vous autoriserez vos utilisateurs à augmenter / compléter l'interface de la classe.
Extension II
Un effet secondaire du point précédent, il est impossible de déclarer des méthodes statiques dans plusieurs en-têtes. Chaque méthode doit être déclarée dans la même classe.
Pour les espaces de noms, les fonctions du même espace de noms peuvent être déclarées dans plusieurs en-têtes (la fonction d'échange presque standard en est le meilleur exemple).
Extension III
La fraîcheur de base d'un espace de noms est que dans certains codes, vous pouvez éviter de le mentionner, si vous utilisez le mot-clé "using":
Et vous pouvez même limiter la "pollution" à une seule classe:
Ce «modèle» est obligatoire pour la bonne utilisation de l'idiome d'échange presque standard.
Et cela est impossible à faire avec des méthodes statiques dans les classes.
Ainsi, les espaces de noms C ++ ont leur propre sémantique.
Mais cela va plus loin, car vous pouvez combiner des espaces de noms d'une manière similaire à l'héritage.
Par exemple, si vous avez un espace de noms A avec une fonction AAA, un espace de noms B avec une fonction BBB, vous pouvez déclarer un espace de noms C et amener AAA et BBB dans cet espace de noms avec le mot-clé using.
Conclusion
Les espaces de noms sont pour les espaces de noms. Les cours sont pour les cours.
C ++ a été conçu pour que chaque concept soit différent et soit utilisé différemment, dans différents cas, comme solution à différents problèmes.
N'utilisez pas de classes lorsque vous avez besoin d'espaces de noms.
Et dans votre cas, vous avez besoin d'espaces de noms.
la source
Il y a beaucoup de gens qui ne seraient pas d'accord avec moi, mais voici comment je le vois:
Une classe est essentiellement une définition d'un certain type d'objet. Les méthodes statiques doivent définir des opérations intimement liées à cette définition d'objet.
Si vous allez simplement avoir un groupe de fonctions connexes non associées à un objet sous-jacent ou à la définition d'un type d'objet , alors je dirais aller avec un espace de noms uniquement. Juste pour moi, conceptuellement, c'est beaucoup plus sensé.
Par exemple, dans votre cas, demandez-vous: "Qu'est-ce qu'un MyMath?" Si
MyMath
ne définit pas une sorte d'objet, alors je dirais: n'en faites pas une classe.Mais comme je l'ai dit, je sais qu'il y a beaucoup de gens qui seraient (même avec véhémence) en désaccord avec moi à ce sujet (en particulier, les développeurs Java et C #).
la source
typedef
les utiliser, les utiliser comme paramètres de modèle, etc.Sinon, utilisez des fonctions d'espaces de noms.
En réponse aux commentaires: oui, les méthodes statiques et les données statiques ont tendance à être sur-utilisées. C'est pourquoi je n'ai proposé que deux scénarios connexes où je pense qu'ils peuvent être utiles. Dans l'exemple spécifique de l'OP (un ensemble de routines mathématiques), s'il voulait pouvoir spécifier des paramètres - par exemple, un type de données de base et une précision de sortie - qui seraient appliqués à toutes les routines, il pourrait faire quelque chose comme:
Si vous n'avez pas besoin que, puis par tous les moyens d' utiliser un espace de noms.
la source
template
arguments!Vous devez utiliser un espace de noms, car un espace de noms présente de nombreux avantages par rapport à une classe:
using
un membre de la classe; vous pouvezusing
un membre d'espace de nomsusing class
, mais ceusing namespace
n'est pas souvent une bonne idéeLes membres statiques sont, à mon avis, très très surutilisés. Ils ne sont pas une réelle nécessité dans la plupart des cas. Les fonctions de membres statiques sont probablement mieux loties que les fonctions de portée de fichier, et les membres de données statiques ne sont que des objets globaux avec une meilleure réputation non méritée.
la source
inline
mot - clé pour satisfaire ODR.inline
, et ce n'est PAS "d'inliner" le corps d'une fonction. Le but réel (et garanti par la norme) duinline
est d'empêcher les définitions multiples. Lisez à propos de "One Definition Rule" pour C ++. En outre, la question SO liée n'était pas compilée en raison de problèmes d'en-tête précompilés au lieu de problèmes ODR.Je préférerais les espaces de noms, de cette façon, vous pouvez avoir des données privées dans un espace de noms anonyme dans le fichier d'implémentation (il n'a donc pas du tout à apparaître dans l'en-tête par opposition aux
private
membres). Un autre avantage est que, parusing
votre espace de noms, les clients des méthodes peuvent refuser de spécifierMyMath::
la source
Une raison de plus pour utiliser la classe - Option pour utiliser des spécificateurs d'accès. Vous pouvez ensuite éventuellement diviser votre méthode statique publique en méthodes privées plus petites. La méthode publique peut appeler plusieurs méthodes privées.
la source
private
méthode most est plus accessible qu'une méthode dont le prototype n'est pas du tout publié dans un en-tête (et reste donc invisible). Je ne mentionne même pas la meilleure encapsulation offerte par les fonctions d'espaces de noms anonymes..cpp
fichier, ce qui les rendrait privées pour cette unité de traduction sans donner d'informations superflues à quiconque lisant le fichier d'en-tête. En fait, j'essaie de défendre l'idiome PIMPL..cpp
fichier si vous souhaitez utiliser des modèles.L'espace de noms et la méthode de classe ont leurs utilisations. L'espace de noms peut être réparti sur plusieurs fichiers, mais c'est une faiblesse si vous devez appliquer tout le code associé pour aller dans un seul fichier. Comme mentionné ci-dessus, la classe vous permet également de créer des membres statiques privés dans la classe. Vous pouvez l'avoir dans l'espace de noms anonyme du fichier d'implémentation, mais il est toujours plus étendu que de les avoir dans la classe.
la source
private:
ceux. et dans de nombreux cas où un accès privilégié semble être requis, cela peut être pris en compte. la fonction la plus «privée» est celle qui n'apparaît pas dans un en-tête.private:
les méthodes ne peuvent jamais bénéficier de cet avantage.