🥥类的作用域
2022-5-15
| 2023-8-2
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
Property
 
每个类都会定义它自己的作用域。在类的作用域之外, 普通的数据和函数成员只能由对象、引用或者指针使用成员访问运算符来访问。对于类类型成员则使用作用域运算符访问。不论哪种情况, 跟在运算符之后的名字都必须是对应类的成员:
 
作用域和定义在类外部的成员
一个类就是一个作用域的事实能够很好地解释为什么在类的外部定义成员函数时必须同时提供类名和函数名。在类的外部,成员的名字被隐藏起来了。
一旦遇到了类名,定义的剩余部分就在类的作用域之内了,这里的剩余部分包括参数列表和函数体。结果就是,可以直接使用类的其他成员而无须再次授权了。
例如,Window_mgr类的clear成员,该函数的参数用到了window_mgr类定义的一种类型:
因为编译器在处理参数列表之前已经明确了当前正位于Window_mgr类的作用域中,所以不必再专门说明ScreenIndexWindow _mgr类定义的。出于同样的原因,编译器也能知道函数体中用到的screens也是在 Window_mgr类中定义的。
 
另一方面,函数的返回类型通常出现在函数名之前。因此当成员函数定义在类的外部时,返回类型中使用的名字都位于类的作用域之外。这时,返回类型必须指明它是哪个类的成员。例如,我们可能向Window_mgr类添加一个新的名为addScreen的函数,它负责向显示器添加一个新的屏幕。这个成员的返回类型将是ScreenIndex,用户可以通过它定位到指定的Screen
因为返回类型出现在类名之前,所以事实上它是位于window_mgr类的作用域之外的。在这种情况下,要想使用screenIndex作为返回类型,必须明确指定哪个类定义了它。
 
 

名字查找与作用域

编译器处理完类中的全部声明后才会处理成员函数的定义。
成员函数体直到整个类可见后才会被处理,因此它能使用类中定义的任何名字。
声明中使用的名字,包括返回类型或参数列表,都必须确保使用前可见。
  • 如果某个成员的声明使用了类中尚未出现的名字,则编译器将会在定义该类的作用域中继续查找。
  • 如果类的成员使用了外层作用域的某个名字,而该名字表示一种类型,则类不能在之后重新定义该名字。
尽管重新定义类型名字是一种错误的行为,但是编译器并不为此负责。一些编译器仍将顺利通过这样的代码,而忽略代码有错的事实。
 
类型名定义通常出现在类起始处,这样能确保所有使用该类型的成员都位于类型名定义之后。
成员函数中名字的解析顺序:
  • 在成员函数内查找该名字的声明,只有在函数使用之前出现的声明才会被考虑。
  • 如果在成员函数内没有找到,则会在类内继续查找,这时会考虑类的所有成员。
  • 如果类内也没有找到,会在成员函数定义之前的作用域查找。
尽管类的成员被隐藏了,但我们仍然可以通过加上类的名字或显式地使用 this 指针来强制访问成员。
类作用域之后,在外围的作用域中查找
如果编译器在函数和类的作用域中都没有找到名字,它将接着在外围的作用域中查找。在前面例子中,名字height定义在外层作用域中,且位于Screen 的定义之前。然而,外层作用域中的对象被名为height的成员隐藏掉了。因此,如果需要的是外层作用域中的名字,可以显式地通过作用域运算符来进行请求:
 
 
尽管外层的对象被隐藏掉了,还是可以通过作用域运算符 :: 或显式 this 指针来强制访问被隐藏的类成员。
 
 
在文件名字的出现处对其进行解析
当成员定义在类的外部时,名字查找不仅要考虑类定义之前的全局作用域中的声明,还需要考虑在成员函数定义之前的全局作用域中的声明。例如:
 
  • C++
  • 友元类的静态成员
    目录