类其实也是一种作用域,每个类都会定义它自己的作用域。在类的作用域之外,普通的成员只能通过对象(可以是对象本身,也可以是对象指针或对象引用)来访问,静态成员既可以通过对象访问,又可以通过类访问,而 typedef 定义的类型只能通过类来访问。
下面的例子使用不同的方式访问了不同的成员:
#include<iostream>
using namespace std;
class A{
public:
typedef int INT;
static void show();
void work();
};
void A::show(){ cout<<"show()"<<endl; }
void A::work(){ cout<<"work()"<<endl; }
int main(){
A a;
a.work(); //通过对象访问普通成员
a.show(); //通过对象访问静态成员
A::show(); //通过类访问静态成员
A::INT n = 10; //通过类访问 typedef 定义的类型
return 0;
}
一个类就是一个作用域的事实能够很好的解释为什么我们在类的外部定义成员函数时必须同时提供类名和函数名。在类的外部,类内部成员的名字是不可见的。
一旦遇到类名,定义的剩余部分就在类的作用域之内了,这里的剩余部分包括参数列表和函数体。结果就是,我们可以直接使用类的其他成员而无需再次授权了。请看下面的例子:
#include<iostream>
using namespace std;
class A{
public:
typedef char* PCHAR;
public:
void show(PCHAR str);
private:
int n;
};
void A::show(PCHAR str){
cout<<str<<endl;
n = 10;
}
int main(){
A obj;
obj.show("http://www.cdsy.xyz");
return 0;
}
我们在定义 show() 函数时用到了类 A 中定义的一种类型 PCHAR,因为前面已经指明了当前正位于 A 类的作用域中,所以不用再使用A::PCHAR这样的冗余形式。同理,编译器也知道函数体中用到的变量 n 也位于 A 类的作用域。
另一方面,函数的返回值类型出现在函数名之前,当成员函数定义在类的外部时,返回值类型中使用的名字都位于类的作用域之外,此时必须指明该名字是哪个类的成员。修改上面的 show() 函数,让它的返回值类型为 PCHAR:
PCHAR A::show(PCHAR str){
cout<<str<<endl;
n = 10;
return str;
}
这种写法是错误的。因为返回值类型 PCHAR 出现在类名之前,所以事实上它是位于 A 类的作用域之外的。这种情况下要想使用 PCHAR 作为返回值类型,就必须指明哪个类定义了它,正确的写法如下所示:
A::PCHAR A::show(PCHAR str){
cout<<str<<endl;
n = 10;
return str;
}