C++中的所有标识符,即名字,都不是在程序的整个过程中都有效的。标识符的这个有效范围,就是标识符的作用域。
标识符的作用域主要分为以下五大类:
(1)局部作用域:限制在符合语句(语句块)内有效的作用域。
(2)全局作用域:有效的范围达到整个源程序文具的作用域。
(3)语句作用域:限制在结构性语句中有效的作用域。
(4)名空间作用域:限制在名空间内有效的作用域;
(5)类作用域:只在类定义体及成员函数定义范围内有效的作用域
名空间作用域:
我们可以将程序中所用的各种名字进行分组,各种名字或者属于某个组,或者不属于任何组。属于不同组的名字可以相同;
标识符的重名是指相同名称的标识符的作用域有重叠。在重名情况下,标识符的作用域必须在不同层的块上(包括全局作用域,及0层的块)。在重叠区域,内层块中定义的标识符将隐藏外层的同名标识符,故重名时标识符默认为内层的标识符。
注:必须是内层再一次定义了相同的标识符,那么内层的标识符将隐藏外层同名的标识符,意思是外层的表示符不会因为内层的改变而改变,如果内层只是使用了外层的标识符,那么就会对外层的表示产生影响。如下代码演示:
#include<iostream>
using namespace std;
int a =100;//0层
void f(int a)//1层形参变量a隐藏了0层的a;
{
int s = -123;
{
char a = 'A';//2层变量a隐藏0层和1层变量a;
cout<<" in f() {} s="<<s<<"\ta="<<a<<endl;
}
cout<<"in f() s="<<s<<"\ta"<<a<<"\t::a="<<::a<<endl;//::a为全局变量(0层)
}
int main()
{
int i=3,j=4,s;//1层变量i,j,s;
s=i*j;
f(19);
cout<<"in main()i="<<i<<"\tj="<<j<<"\ts"<<s<<endl;
{
double i =7.9;//2层变量i,隐藏了1层的i
double s;
s = i*j; //i为2层的i(double),s值发生了改变
cout<<"in main(){}i="<<i<<"\tj="<<j<<"\ts"<<s<<endl;
}
f(23);
cout<<"int main(){}i"<<i<<"\tj="<<j<<"\ts="<<s<<endl;
return 0;
}
#include<iostream>
using namespace std;
int a =100;//0层
void f(int a)//1层形参变量a隐藏了0层的a;
{
int s = -123;
{
char a = 'A';//2层变量a隐藏0层和1层变量a;
cout<<" in f() {} s="<<s<<"\ta="<<a<<endl;
}
cout<<"in f() s="<<s<<"\ta"<<a<<"\t::a="<<::a<<endl;//::a为全局变量(0层)
}
int main()
{
int i=3,j=4,s;//1层变量i,j,s;
s=i*j;
f(19);
cout<<"in main()i="<<i<<"\tj="<<j<<"\ts"<<s<<endl;
{
double i =7.9;//2层变量i,隐藏了1层的i
//double s;
s = i*j; //i为2层的i(double),s值发生了改变
cout<<"in main(){}i="<<i<<"\tj="<<j<<"\ts"<<s<<endl;
}
f(23);
cout<<"int main(){}i"<<i<<"\tj="<<j<<"\ts="<<s<<endl;
return 0;
}
可以看到在最后一条的结果中s的值不同,区别就在于是否重新定义了s;
函数说明的隐藏规则:
若函数定义在函数调用的后面,则之前需要进行函数的说明。函数说明通常放在所有还是你说的前面。当然,函数说明也可以放在函数内部作为局部说明;
同名函数的说明可以在块的不同层次进行说明,若内层块中有同名函数的说明,该说明则隐藏一切外部同名函数的说明。换言之,当内层函数说明与外层函数说明有不同的参数表时,仍然隐藏外层函数的说明,即外层同名函数尽管参数表不同也不能在内层使用,除非内层也做了同样参数表的同名函数(重载说明);
include<iostream>
using namespace std;
int main()
{
void f(),f(int x);
f();
f(3);
{
void f(double x);//隐藏了说明void f(),f(int x);
f(3.1);
//f();//错误,因为函数说明void f();被内层说明隐藏;
}
return 0;
}
void f(){cout<<"f()"<<endl;}
void f(int x){cout<<"f(int x)"<<endl;}
void f(double x){cout<<"f(double x)"<<endl;}