Namespaces
Variants

Nested classes

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

在另一个类内部可以出现 类/结构体 联合体 的声明。这样的声明被称为 嵌套类

说明

嵌套类的名称存在于外围类的作用域内,从嵌套类成员函数进行的名称查找会在检查嵌套类作用域后访问外围类的作用域。与外围类的任何成员类似,嵌套类可访问外围类能访问的所有名称(私有、受保护等),但除此之外它是独立的,且对外围类的 this 指针 没有特殊访问权限。嵌套类中的声明可以使用外围类的任何成员,遵循 非静态成员的常规使用规则

int x, y; // 全局变量
class enclose // 外围类
{
    // 注意:私有成员
    int x;
    static int s;
public:
    struct inner // 嵌套类
    {
        void f(int i)
        {
            x = i; // 错误:没有实例无法写入非静态成员 enclose::x
            int a = sizeof x; // C++11 前错误,
                              // C++11 正常:sizeof 的操作数不被求值,
                              // 允许这样使用非静态成员 enclose::x
            s = i;   // 正常:可以赋值给静态成员 enclose::s
            ::x = i; // 正常:可以赋值给全局变量 x
            y = i;   // 正常:可以赋值给全局变量 y
        }
        void g(enclose* p, int i)
        {
            p->x = i; // 正常:赋值给 enclose::x
        }
    };
};

友元 函数在嵌套类内部定义时,即使从嵌套类内部定义的成员函数体中进行查找可以找到外围类的私有成员,这些友元函数也并不会有访问外围类成员的特殊权限。

嵌套类成员的外部类定义出现在外围类的命名空间中:

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

嵌套类可以进行前向声明并在之后定义,可以在同一个外围类体内或在其外部:

class enclose
{
    class nested1;    // 前向声明
    class nested2;    // 前向声明
    class nested1 {}; // 嵌套类定义
};
class enclose::nested2 {}; // 嵌套类定义

嵌套类声明遵循 成员访问 说明符,私有成员类无法在封闭类作用域之外被命名,尽管该类的对象可以被操作:

class enclose
{
    struct nested // 私有成员
    {
        void g() {}
    };
public:
    static nested f() { return nested{}; }
};
int main()
{
    //enclose::nested n1 = enclose::f(); // 错误:'nested' 是私有成员
    enclose::f().g();       // 正确:未直接使用 'nested' 名称
    auto n2 = enclose::f(); // 正确:未直接使用 'nested' 名称
    n2.g();
}

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

DR 适用范围 已发布行为 正确行为
CWG 45 C++98 嵌套类的成员无法访问
其外围类及其友元
它们具有与外围类其他成员
相同的访问权限
(同时解决了 CWG 问题 #8 和 #10)

参考文献

  • C++23 标准 (ISO/IEC 14882:2024):
  • 11.4.12 嵌套类声明 [class.nest]
  • C++20 标准 (ISO/IEC 14882:2020):
  • 11.4.10 嵌套类声明 [class.nest]
  • C++17 标准 (ISO/IEC 14882:2017):
  • 12.2.5 嵌套类声明 [class.nest]
  • C++14 标准 (ISO/IEC 14882:2014):
  • 9.7 嵌套类声明 [class.nest]
  • C++11 标准 (ISO/IEC 14882:2011):
  • 9.7 嵌套类声明 [class.nest]
  • C++98 标准 (ISO/IEC 14882:1998):
  • 9.7 嵌套类声明 [class.nest]