5.12 局部类

简介

类可以定义在某个函数的内部,我们称这样的类为局部类local class

  • 局部类的成员必须完整定义在类的内部,所以成员函数的复杂性不能太高,一般只有几行代码

  • 在局部类中不允许声明静态数据成员

局部类不能使用函数作用域中的变量

局部类只能访问外层作用域定义的类型名、静态变量以及枚举成员。如果局部类定义在某个函数内部,则该函数的普通局部变量不能被该局部类使用:

int a, val;
void foo(int val) {
    static int si;
    enum Loc { a = 1024, b };
    // Bar是foo的局部类
    struct Bar {
        Loc locVal;          // 正确: 使用一个局部类型名
        int barVal;
        
        void fooBar(Loc l = a) {
            barVal = val;    // 错误: val是foo的局部变量
            barVal = ::val;  // 正确: 使用一个全局变量
            barVal = si;     // 正确: 使用一个静态局部对象
            locVal = b;      // 正确: 使用一个美剧成员
        }
    };
    // ...
}

常规的访问保护规则对局部类同样适用

外层函数对局部类的私有成员没有任何访问特权。当然,局部类可以将外层函数声明为友元;或者更常见的是局部类将其成员声明成公有的。在程序中有权访问局部类的代码非常有限,局部类已经封装在函数作用域中,通过信息隐藏进一步封装就显得没有必要。

局部类中的名字查找

局部类内部的名字查找次序与其他类相似。在声明类的成员时,必须先确保用到的名字位于作用域中,然后再使用该名字。定义成员时用到的名字可以出现在类的任意位置,如果某个名字不是局部类的成员,则继续在外层函数函数作用域中查找。如果还是没有找到,则在外层函数所在的作用域中查找。

嵌套的局部类

可以在局部类的内部再嵌套一个类。此时嵌套类的定义可以出现在局部类之外,不过嵌套类必须定义在于局部类相同的作用域中。

void foo() {
    class Bar {
     public:
        // ...
        class Nested;
    };
    
    class Bar::Nested {
        // ...
    };
}

局部类内的嵌套类也是一个局部类,必须遵循局部类的各种规定。嵌套类的所有成员都必须定义在嵌套类内部。