64 votes

Que signifie la syntaxe C ++ “A :: B: A {};”

Que signifie syntaxe C ++ struct A::B:A {}; ? Où cette définition de nom (ou d'accès) est-elle décrite dans la norme C ++?

 #include <iostream>

struct B;

struct A {
    struct B;
};

struct A::B:A {
};

int main() {
    A::B::A::B b;
    std::cout<<"Sizeof A::B::A::B is " << sizeof(A::B::A::B)<<std::endl;
    return 0;
}
 

119voto

StoryTeller Points 6139

Cette définition

struct A {
    struct B;
};

Définit une structure (struct) A avec une déclaration de imbriquée struct B1. Le nom complet de l' B est A::B, vous pouvez dire B est à l'intérieur de l' "espace de noms" de A. Puis ceci:

struct A::B : A { // Note I added spaces
};

Est la définition de l' A::B, et le single : indique qu'il est dérivé à partir d' A.

Maintenant, la partie la plus intéressante est A::B::A::B. Nous allons disséquer:

  1. A::B noms de la structure imbriquée.
  2. A::B::A accède à la injecté nom de la classe A à l'intérieur d' B. L'injection est en raison de l'héritage.
  3. A::B::A::B noms de la structure imbriquée B en A de nouveau.

Et vous pouvez continuer ad vitam aeternam, ou au moins jusqu'à ce que votre compilateur rencontre sa traduction limite de2.

Un amusant exercice intellectuel, mais évitez comme la peste dans le code réel.


[classe.qual]/1 explique comment la recherche fonctionne

Si la nested-nom-spécificateur d'un personnel qualifié-id désigne une classe, l' le nom spécifié après la nested-nom-spécificateur est recherché dans le la portée de la classe ([classe.membre.recherche]), sauf pour les cas énumérés ci-dessous. Le nom doit représenter un ou plusieurs membres de cette de la classe ou de l'une de ses classes de base (Clause [classe.dérivés]).

Et le texte ci-dessus nous permet de le nom de la classe de base, parce que [la classe]/2

Le nom de classe est également inséré dans le champ d'application de la classe elle-même; ceci est connu comme la injecté de nom de classe. Pour les fins de l'accès vérifier la injecté de nom de classe est traité comme s'il s'agissait d'un public nom de membre.

Le ci-dessus indique clairement que, à partir d'un nom qualifié complet avec A:: vous permet de spécifier un membre ou d'une classe de base. Depuis A n'a pas de bases, vous pouvez uniquement spécifier A::B (un "type de membre"). Mais A::B désigne aussi une classe. Donc on peut spécifier une base ou d'un membre de que aussi bien avec A::B::, ce qui nous permet de nommer A::B::A. Maintenant, rincer et répéter.


1 - Notez qu'il s'agit d'une tout autre B. Pas du tout liées à l'global struct B.
2 - Un minimum de 256 selon [implimits]/2.36

21voto

VTT Points 27056

Tout d'abord struct B; est une déclaration anticipée de struct B dans l'espace de noms global. Il pourrait être source de confusion car il n'est pas réellement pertinent dans cet exemple. Cette B peut être consulté en tant que ::B ou juste B.

struct A {
    struct B;
};

Est une définition de la struct A dans l'espace de noms global à l'avant d'une déclaration de imbriquée struct B (pas le même que précédemment déclarée B dans l'espace de noms global). Cette imbriquée B peut être consulté en tant que ::A::B ou A::B.

struct A::B:A {
};

Est une définition de imbriquée struct B de struct A qui hérite de A (avec accès spécificateur omis). Il peut être réécrit pour:

struct A::B
:   public A
{
};

Notez que l'écriture de la définition de imbriquée struct B à l'intérieur de l' A définition comme cela ne fonctionne pas:

struct A {
    struct B: A { // error: A is incomplete at this point
    };
};

Et enfin A::B::A fait référence à la classe de base de imbriquée struct B, c'est-à - A, alors A::B::A::B est l'équivalent d'un peu A::B.

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