一、类的作用域
(1)每个类都定义了自己的作用域和唯一的类型。在类体内声明类成员,将成员名引入类的作用域中。两个不同的类具有两个独立的类作用域。即使两个类具有完全相同的成员列表,它们也是不同的类型。每个类的成员不同于任何其他类的成员。例如:
(2)在类作用域之外,成员只能通过对象、指针或引用的方式 (使用成员访问操作符“.”或“->”)来访问。这些运算符左边的运算对象分别是一个类对象、指向类对象的指针或对象的引用,后面的 成员名字必须在相对应的类的作用域中声明。
(3)静态成员、类中定义的类型成员需要直接通过类作用域运算符“::”来访问。
(4)定义于类外部的成员函数的形参列表和函数体也都是在类作用域中,所以可以直接引用类的其他成员。例如:
1.类作用域中的名字查找
名字查找(name lookup),即寻找与给定的名字相匹配的声明的过程。
①首先,在使用该名字的块中查找名字的声明,且只考虑在该名字使用之前声明的名字;
②如果找不到该名字,则在包围的作用域中查找;
③如果找不到任何声明,则编译错误。
比较容易引起混淆的是在类体内定义的名字。
(1)类成员声明的名字查找。
按以下方式确定在类成员的声明中用到的名字:
①检查出现在名字使用之前的类成员的声明。
②如果①查找不成功,则检查包含类定义的作用域中出现的声明以 及出现在类定义之前的声明。
必须在类中先定义类型名字,才能将它们用作数据成员的类型,或者成员函数的返回类型或形参类型。编译器按照成员声明在类中出现的次序来处理名字。
(2)类成员定义中的名字查找。
按以下方式确定在成员函数的函数体中用到的名字。
①首先检查成员函数局部作用域中的声明;
②如果在成员函数中找不到该名字的声明,则检查所有类成员的声明;
③如果在类中找不到该名字的声明,则检查在此成员函数定义之前的作用域中出现的声明。
2. 嵌套类
可以在类A的内部定义类B,称类B为嵌套类(nested class),又称为嵌套类型(nested type),称类A为外围类(enclosing class)。 例如:
说明:
(1)嵌套类是独立的类,基本上与它们的外围类不相关,因此,外围类和嵌套类的对象是互相独立的。嵌套类型的对象不包含外围 类所定义的成员,同样,外围类的成员也不包含嵌套类所定义的成 员。
(2)嵌套类的名字只在其外围类的作用域中可见,嵌套类的名字 不会与另一作用域中声明的名字冲突。
(3)嵌套类可以具有与非嵌套类相同种类的成员。像任何其他类一样,嵌套类使用访问标号控制对自己成员的访问。成员可以声明为public、private或protected。外围类对嵌套类的成员没有特殊访问权,并且嵌套类对其外围类的成员也没有特殊访问权。
(4)在外围类的public部分定义的嵌套类定义了可在任何地方使用 的类型,在外围类的protected部分定义的嵌套类定义了只能由外 围类、友元或派生类访问的类型,在外围类的private部分定义的嵌 套类定义了只能被外围类或其友元访问的类型。
►嵌套类可以直接引用外围类的静态成员、类型名和枚举成员,当然,引用外围类作用域之外的类型名或静态成员,需要作用域运算符 (::)。
3. 局部类
可以在函数体内部定义类,这样的类称为局部类。一个局部类定义了一个类型,该类型只在定义它的局部作用域中可见。
按生命期的不同,对象可分为如下四种:
(1)局部对象。局部对象在运行函数时被创建,调用构造函数;当函数运行结束时被释放,调用析构函数。
(2)静态局部对象。 静态局部对象在程序执行函数第一次经过该对象的定义语句时被创 建,调用构造函数。这种对象一旦被创建,在程序结束前都不会撤销。即使定义静态局部对象的函数结束时,静态局部对象也不会撤销。在该函数被多次调用的过程中,静态局部对象会持续存在并保持它的值。 静态局部对象在程序运行结束时被释放,调用析构函数。
(3)全局对象 。全局对象在程序开始运行时,main运行前创建对象,并调用构造函数;在程序运行结束时被释放,调用析构函数。
(4)自由存储对象 。用new分配的自由存储对象在new运算时创建对象,并调用构造函数;在delete运算时被释放,调用析构函数。自由存储对象一经 new运算创建,就会始终保持直到delete运算时,即使程序运行结束它也不会自动释放。