Namespaces
Variants
Views
Actions

nested types

From cppreference.com
< cpp‎ | language
Revision as of 12:46, 24 September 2013 by Cubbi (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

A declaration of a class/struct or union may appear in within another class. Such declaration declares a nested class

Explanation

The name of the nested class exists in the scope of the enclosing class, and name lookup from a member function of a nested class visits the scope of the enclosing class after examining the scope of the nested class, but it is otherwise completely independent and has no special access to the enclosing class:

int y; // global y
struct enclose { // enclosing class
    int x;
    static int s;
    struct inner { // nested class
        void f(int i) {
            x = i; // Error: can't write to non-static enclose::x without instance
            int a = sizeof(x); // OK: operand of sizeof is unevaluated
            s = i; // OK: can assign to the static enclose::s
            ::x = i; // OK: can assign to global x
            y = i; // OK: can assign to global y
        }
        void g(enclose* p, int i) {
            p->x = i; // OK: assign to enclose::x
        }
    };
};

Similarly, friend functions defined in a nested class have no special access to the enclosing class.

Out-of-class definitions of the members of a nested class appear in the namespace of the enclosing class:

struct enclose {
    struct inner {
        static int x;
        void f(int i);
    };
};
int enclose::inner::x = 1; // definition
void enclose::inner::f(int i) {} // definitino

Nested classes can be forward-declared and later defined, either within the same enclosing class body, or outside of it:

class enclose {
    class nested1; // forward declaration
    class nested2; // forward declaration
    class nested1 {}; // definition of nested class
};
class enclose::nested2 { }; // definition of nested class

Nested class declarations obey member access specifiers, a private member class cannot be named outside the scope of the enclosing class, although objects of that class may be manipulated:

class enclose {
    struct nested { // private member
        void g() {}
    };
 public:
    static nested f() { return nested{}; }
};
 
int main()
{
    //enclose::nested n1 = e.f(); // error: 'nested' is private
 
    enclose::f().g(); // OK: does not name 'nested'
    auto n2 = enclose::f(); // OK: does not name 'nested'
    n2.g();
}

References

  • C++11 standard (ISO/IEC 14882:2011):
  • 9.7 Nested class declarations [class.nest]
  • C++98 standard (ISO/IEC 14882:1998):
  • 9.7 Nested class declarations [class.nest]