嵌套类

< cpp‎ | language

class/structunion 的声明可以在另一个类中出现。这种声明声明一个嵌套类(nested class)

解释

嵌套类的名字存在于其外围类作用域中,而且从嵌套类的成员函数中进行名字查找,在检测嵌套类的作用域后将访问外围类的作用域。与其外围域的任何成员相似,对所有外围类拥有访问权的名字(私有、受保护等),嵌套类也拥有访问权,但其他方面它是独立的,而且对外围类的 this 指针无特定访问权。

嵌套类中的声明只能使用外围类中的类型名、静态成员及枚举项。 (C++11 前)

嵌套类中的声明能使用外围类的所有成员,遵循非静态成员的常规使用规则

(C++11 起)
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 中 OK:sizeof 的操作数不求值,
                              // 非静态 enclose::x 的此种用法是允许的。
            s = i;   // OK:可赋值给静态 enclose::s
            ::x = i; // OK:可赋值给全局 x
            y = i;   // OK:可赋值给全局 y
        }
        void g(enclose* p, int i) {
            p->x = i; // OK:赋值给 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 = e.f(); // 错误:'nested' 为私有
 
    enclose::f().g(); // OK:并未指名 'nested'
    auto n2 = enclose::f(); // OK:并未指名 'nested'
    n2.g();
}

引用

  • 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]