1.类的作用域
类的作用域之外,普通的数据和函数成员只能由对象、引用或者指针访问运算符来访问。对于类类型成员,
则使用作用域运算符来访问。
Screen::pos ht =24,wd = 80;
Screen scr(ht,wd,'');
Screen *p = &scr;
char c = scr.get(); //访问scr对象的get成员
c = p->get(); //访问p所指对象的get成员
**作用域和定义在类外部的成员**
class Window_mgr {
public:
// 窗口中每个屏幕的编号
using ScreenIndex = std::vector <Screen>::size_type;
//按照编号将指定的Screen重置为空白
void clear(ScreenIndex);
private:
std::vector <Screen> screens{Screen(24,80,'')};
};
void Window_mgr::clear(ScreenIndex i)
{
//s是一个Screen的引用,指向我们想要清空的那个屏幕
Screen &s =screen[i];
//将那个选定的Screen重置空白
s.contents = string(s.height *s.width,'');
}
如上所示程序,ScreenIndex和screen是在Window_mgr类中定义的。
函数的返回类型通常出现在函数名之前。因此当成员函数定义在类的外部时,返回类型中使用的名字都位于
类的作用域之外。这时,返回类型必须指明它是哪个类的成员。
class Window_mgr {
public:
//向窗口添加一个Screen,返回它的编号
ScreenIndex addScreen (const Screen&);
};
//首先处理返回类型,之后我们才进入Window_mgr的作用域
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s)
{
screen.push_back(s);
return screen.size()-1;
}
如上所示的例子中,要想使用ScreenIndex作为返回类型,我们必须明确指定哪个类定义了它。
**名字查找**
名字查找是指寻找与所用名字最匹配的声明的过程。
**用于类成员声明的名字查找**
声明中使用的名字,包括返回类型或者参数列表中使用的名字,都必须保证在使用前确保可见。如果某个成员的声明
使用了类中尚未出现的名字,则编译器将会在定义该类的作用域中继续查找。
**类型名要特殊处理**
内层作用域可以重新定义外层作用域中的名字,即使该名字已经在内层作用域中使用过。然而在类中,如果成员使用
了外层作用域中的某个名字,而该名字代表一种类型,则类不能在之后重新定义该名字:
typedef double Money;
class Account {
public:
Money balance() {return bal;} //使用外层作用域的Money
private:
typedef double Money; //错误:不能重新定义Money
Money bal;
};
类型名的定义通常出现在类的开始处,这样就能确保所有使用该类型的成员都出现在类名的定义之后。
**成员定义中的普通块作用域的名字查找**
成员函数中使用的名字按照如下方式解析:
(1)首先,在成员函数内查找该名字的声明。同理,只有在函数使用之前出现的声明才被考虑。
(2)如果在成员函数内没有找到,则在类内继续查找,这时,类的所有成员都可以被考虑。
(3)如果类内也没有找到该名字的声明,在成员函数定义之前的作用域内继续查找。
尽管类的成员被隐藏了,但我们仍然可以通过加上类的名字或者显式地使用this指针来强制访问成员。
**类作用域之后,在外围的作用域中查找**
如果我们需要的是外层作用域中的名字,可以显式地通过作用域运算符(::)进行请求。
**在文件中名字的出现处对其进行解析**
当成员定义在类的外部时,名字查找的第三步不仅要考虑类定义之前的全局作用域中的声明,还需要考虑
在成员函数定义之前的全局作用域中的声明。
int height; //定义了一个名字,稍后将在Screen中使用
class Screen {
public:
typedef std::string::size_type ops;
void setHeight(pos);
pos height = 0; //隐藏外层作用域中的height
};
Screen::pos verify(Screen::pos);
void Screen::setHeight(pos var) {
// var: 参数
// height: 类的成员
// verify: 全局函数
height = verify(var); //verify的声明位于setHeight的定义之前,因此可以被正常使用。
}