类可以定义在某个函数的内部,称这样的类为局部类。局部类定义的类型只在定义它的作用域内可见。
和嵌套类不同,局部类的成员受到严格限制。
- 局部类的成员函数一般不会特别复杂,一般只有几行代码。
- 在局部类中不允许声明静态数据成员,因为没法定义这样的成员。
局部类不能使用函数作用域中的变量
局部类对其外层作用域中名字的访问权限受到很多限制,局部类只能访问外层作用域定义的类型名、静态变量以及枚举类型。
如果局部类定义在某个函数内部,则该函数的普通局部变量不能被该局部类使用:
int a, val;
void foo(int val)
{
static int s_i;
enum Loc{a=1024,b};
struct Bar {
Loc locVal;
int barVal;
void fooBar(Loc l = a)
{
barVal = val; //@ error,val 是 foo 的局部变量
barVal = ::val; //@ ok,使用一个全局对象
barVal = s_i; //@ ok,使用一个静态局部变量
locVal = b; //@ ok,使用一个枚举成员
}
};
//@ ....
}
常规的访问保护规则对局部类同样适用
外层函数对于局部类的私有成员并没有任何特殊的访问权限。局部类可以将外层函数声明为友元,或者更常见的方式是局部类将其成员声明成公有的。
程序中有权访问局部类的代码非常有限,局部类已经封装在函数作用域,通过信息隐藏进一步封装显得没什么必要。
局部类中的名字查找
局部类内部的名字查找次序与其他类相似。在声明类的成员时,必须先确保用到的名字位于作用域中,然后再使用该名字。定义成员时用到的名字可以出现在类的任意位置:如果名字不是局部类的成员,则继续在外层函数作用域中查找;如果没有找到,则在外层函数所在作用域中查找。
嵌套的局部类
可以在局部类的内部再嵌套一个类,此时嵌套类的定义可以出现在局部类之外,不过,嵌套类必须定义在于局部类相同的作用域中。
void foo()
{
class Bar {
public:
//@ ...
class Nested; //@ 声明 Nested 类
};
//@ 定义 Nested 类
class Bar::Nested {
//@ ...
};
}
内部嵌套类也是一个局部类,也需要遵守局部类的各种规定。