What does C++ syntax “A::B:A {};” mean

前端 未结 2 1616
谎友^
谎友^ 2020-12-23 12:57

What does C++ syntax struct A::B:A {}; mean? Where is this name definition (or access) described in the C++ standard?

#include 
         


        
相关标签:
2条回答
  • 2020-12-23 13:56

    This definition

    struct A {
        struct B;
    };
    

    Defines a struct A with a declaration of a nested struct B1. The fully qualified name of B is A::B, you could say B is inside the "namespace" of A. Then this:

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

    Is the definition of A::B, and the single : specifies that it is derived from A.

    Now, the interesting part is A::B::A::B. Let's dissect it:

    1. A::B names the nested structure.
    2. A::B::A accesses the injected class name A inside B. The injection is due to the inheritance.
    3. A::B::A::B names the nested structure B in A again.

    And you can continue ad-infinitum, or at least until your compiler meets its translation limit2.

    A fun intellectual exercise, but avoid like the plague in actual code.


    [class.qual]/1 explains how the lookup works

    If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-name-specifier is looked up in the scope of the class ([class.member.lookup]), except for the cases listed below. The name shall represent one or more members of that class or of one of its base classes (Clause [class.derived]).

    And the text above allows us to name the base class because [class]/2

    The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.

    The above clearly says that starting a fully qualified name with A:: allows you to specify a member or a base class. Since A has no bases, you can only specify A::B (a "member type"). But A::B also nominates a class. So we may specify a base or member of that as well with A::B::, which allows us to name A::B::A. Now rinse and repeat.


    1 - Note it's a completely other B. Not at all related to the global struct B.
    2 - A recommended minimum of 256 according to [implimits]/2.36

    0 讨论(0)
  • 2020-12-23 13:57

    First of all struct B; is a forward declaration of struct B in global namespace. It might be confusing because it is actually not relevant in this example. This global B can be accessed as ::B or as just B.

    struct A {
        struct B;
    };
    

    Is a definition of struct A in global namespace with a forward declaration of nested struct B (not the same as previously declared B in global namespace). This nested B can be accessed as ::A::B or A::B.

    struct A::B:A {
    };
    

    Is a definition of nested struct B of struct A that inherits from A (with access specifier omitted). It can be rewritten to:

    struct A::B
    :   public A
    {
    };
    

    Note that writing definition of nested struct B inside of A definition like this won't work:

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

    And finally A::B::A is referring to the base class of nested struct B, that is to A, so A::B::A::B is equivalent to just A::B.

    0 讨论(0)
提交回复
热议问题