11
votes

Définition de la classe d'espace de noms anonyme

Je cherchais sur un code (C ++) et j'ai trouvé quelque chose comme ceci:

//Foo.cpp
namespace
{
    void SomeHelperFunctionA() {}
    void SomeHelperFunctionB() {}
    void SomeHelperFunctionC() {}

    //etc...    

    class SomeClass //<---
    {
        //Impl
    };
}


0 commentaires

5 Réponses :


8
votes

Un espace de noms anonyme est comme le mot clé statique lorsqu'il est appliqué au niveau mondial.

Un espace de noms anonyme le rend afin que vous ne puissiez rien appeler à l'intérieur de l'espace de noms d'un autre fichier. P>

Les espaces de noms anonymes vous permettent de limiter la portée de ce qui se trouve dans le fichier actuel uniquement. P>

Le programmeur aurait fait cela pour éviter les conflits de noms. Aucun nom mondial ne sera conflit de cette manière à la date de liaison forte>. P>

Exemple: p>

fichier: test.cpp strong> p >

void CallABC();//You can use ABC from this file but not A, B and C

void A()
{
//Do something different
}

int main(int argc, char** argv)
{
  CallABC();
  A();//<--- calls the local file's A() not the other file. 
  return 0;
}


4 commentaires

Merci Brian, je comprends qu'un espace de noms anonyme crée un espace de noms distinct avec un nom unique qui l'empêche. Mais comment cette entreprise de liaison interne / externe s'applique-t-elle aux classes? Désolé si je n'étais pas clair dans ma question.


Marqué comme répondu; plus d'effort, et plus complet. ;) Merci.


EDIT: La fonction de test.cpp est appelée "callabc", alors que tout autre code se réfère comme "ABC" - pourriez-vous mettre à jour un ou les autres? Merci!


Votre dernière phrase suggère que d'autres fichiers seraient en mesure d'utiliser la classe si ce n'était pas dans un espace de noms anonyme. Mais essayez de la compiler comme ça et regardez la table des symboles du fichier d'objet, par ex. avec objdump -t . Les fonctions libres auront leurs symboles exposés, mais les fonctions membres de la classe ne seront pas. J'ai du mal à trouver une référence à cela dans la norme, mais on dirait que la classe agit effectivement comme si elle est sous liaison interne, même sans l'espace de noms anonyme.



1
votes

Si quelqu'un relie ce code et que la définition d'une classe nommée identique incluse et que ce fichier est lié avant l'autre implémentation que vous auriez un conflit de nom.


2 commentaires

Eh bien, cela a plus de sens maintenant. Merci!


En supposant que la classe est pas défini dans l'espace de noms anonyme, c'est-à-dire ??



1
votes

Dans la norme C ++ ISO (Section 2.3), vous trouverez une règle appelée la règle d'une définition . .

En raison de la relation complexe en C ++ entre la compilation et la liaison, ce n'est pas une règle très simple. La plupart des détails sont ici .

Mais cela s'applique aux fonctions membres d'une classe, car elles sont (au niveau de liaison) fonctionnent simplement avec des noms longs.

Il s'applique de manière légèrement différente des modèles, car la lieur rejetera volontiers les définitions supplémentaires des classes de modèle ou des fonctions qui apparaissent dans des unités de traduction distinctes (fichiers source). Cela signifie que si vous fournissez deux définitions différentes du même modèle, votre programme a un comportement indéfini (le meilleur scénario des cas: une des définitions sera choisie silencieusement au hasard).


0 commentaires

1
votes

J'ai eu l'impression que vous pourriez avoir des cours avec des noms identiques dans différentes unités de traduction sans aucune sorte de collision de nommage à condition que vous n'aviez pas de déclaration de classe mondiale

Eh bien, ce n'est pas le cas. N'oubliez pas que ces définitions de classes mondiales "communes" sont dans les fichiers d'en-tête. Celles-ci sont littéralement incluses, copiant cette définition de classe mondiale commune à toutes les unités de traduction. Si vous utilisez une autre façon d'inclure exactement les mêmes définitions de classe dans plusieurs unités de traduction (par exemple, une expansion macro), c'est bien aussi. Mais si vous avez des définitions différentes pour le même nom de classe, vous risquez un comportement indéfini. Link échecs si vous êtes chanceux.


0 commentaires

0
votes

Pour répondre à votre question directement, je pense que cela consiste à éviter les erreurs de liens "multiples définitions" pour STATIC STRAND> MEMBRES DE SOMECLASS. C'est-à-dire que supposons que la somlasse soit définie dans un fichier CPP sans espace de noms anonyme et il existe des champs statiques et / ou des méthodes statiques et ces membres statiques sont définis à côté de la définition de la classe dans ce fichier très cpp. Ensuite, ces membres statiques obtiennent la liaison externe (sont présentes dans la table des symboles du fichier .O correspondant comme global).

Vous avez maintenant un autre fichier CPP et vous souhaitez créer une autre soméclass (sans rapport avec celui-là dans le premier fichier CPP et vous n'êtes peut-être même pas au courant de l'existence du premier soméclas dans ce premier fichier CPP) pour votre propres fins et encore sans espace de noms anonyme. Et vous définissez un membre statique avec le même nom qu'un membre statique du premier somlass. Et vous êtes ici: vous vous retrouvez avec un conflit de liaison. P>

L'auteur du premier fichier du CPP aurait donc caché la première Sameclass à l'intérieur d'un espace de noms anounmis, car la classe était clairement censée être une implémentation détail, plutôt qu'une classe réutilisée par d'autres personnes. De sorte que ses membres statiques ne doivent donc pas avoir une liaison externe. P>

Globalement, ce que j'essaie de dire, c'est que les membres statiques non-Constexpr / non intégrés d'une classe sont comme des variables globales ou des fonctions non lignées . Ainsi, leur liaison peut être faite interne à l'aide d'un espace de noms anonyme, comme il peut être fait pour les variables globales et les fonctions à l'aide de mots-clés statiques ou à nouveau un espace de noms anonyme. P>

// .cpp file
namespace 
{
    struct A
    {
        static int i;
    };
}

int A::i;


0 commentaires