作用域
作用域的定义
作用域是一个标识符(变量、常量、函数等)在程序正文中有效的区域。
作用域分类
- 函数原型作用域
- 局部作用域(块作用域)
- 类作用域
- 全局作用域(文件作用域)
- 命名空间作用域。
函数原型作用域
即参数表。函数原型中的参数,其作用域始于"(",结束于")"。
例:
double area(double radius);
局部作用域
-
函数的形参、在块中声明的标识符。
-
一般的大括号也具有限制代码块的作用,一个大括号就是一个局部作用域。
-
标识符的局部生存期自声明处起,限于块中,通常以“}”结束。
局部作用域举例
void fun(int a) {
int b = a;
cin >> b;
if (b > 0) {
int c;
......
}
}
类作用域
域的大小界定
类的成员具有类作用域,其范围包括类体和非内联成员函数的函数体。
访问控制
如果在类作用域以外访问类的成员,要通过类名(访问静态成员),或者该类的对象名、对象引用、对象指针(访问非静态成员)。
类内常量和枚举类
类内常量需要定义为
static const typename foobar = val;
//或利用枚举方式,目的都是在编译时确定好这些常量
enum {foobar = val};
枚举类型可能会发生标识符名冲突,在C++11下可以使用enum class
或者enum struct
,利用作用域分辨符::
进行区别。
enum class egg{big, small, large};
enum class shirt{big, small, large};
使用时
egg choice = egg::large;
shirt FLUO= shirt::large;
可见性
可见性是从对标识符的引用的角度来谈的概念,表示从内层作用域向外层作用域“看”时能看见什么。
可见性:如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则称该标识符在内层可见。
- 如果标识在某处可见,就可以在该处引用此标识符。
- 对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则外层作用域的标识符在内层不可见。
应用注意事项(仅一点):
嵌套作用域的重名问题域内和域外的同名变量,标识符使用域内变量。
生存期&作用域同这个标识符的可见性没有直接关系。可见性只和嵌套作用域的重名问题相关。
生存期
- 静态生存期:只要程序开始运行,这种生存期的变量就被分配了内存,这种变量的生存期和程序的运行期相同
对应作用域问题中的文件作用域的标识符和static、enum成员
- 局部生存期:这种变量的生存期开始于程序执行经过其声明点时,而结束于命名它的标识符所在的作用域尾(一般是
}
) - 动态生存期:这种变量可以随时创建,随时删除,创建和删除是程序员用内存操作函数进行的。
以下这个例子将说明:
- 静态生存期意味着程序起止的寿命,不一定和全局作用域对应,如a,在
other()
函数内部是内层,出了函数就是外层的a。(可见性的问题) - 局部生存期和局部作用域对应,如
other()
中的局部变量c。 - 各种寿命的标识符都要受到可见性的制约,a、b、c都是如此。
#include<iostream>
using namespace std;
int i = 1; // i 为全局变量,具有静态生存期。
void other() {
static int a = 2;
static int b;
// a,b为静态局部变量,具有全局寿命,局部可见。
//只第一次进入函数时被初始化。
int c = 10; // C为局部变量,具有动态生存期,
//每次进入函数时都初始化。
a += 2; i += 32; c += 5;
cout<<"---OTHER---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
b = a, c = a;
}
int main() {
static int a;//静态局部变量,有全局寿命,局部可见。
int b = -10; // b, c为局部变量,具有动态生存期。
int c = 0;
cout << "---MAIN---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
//---MAIN---
//i: 1 a: 0 b: -10 c: 0
//注意:static变量默认初始化为0
c += 8; other();
//---OTHER---
//i: 33 a: 4 b: 0 c: 15
//i具有全局作用域,所以在函数中被操作。
//b是默认初始化的static变量
//a是全局变量,c是局部变量,但都在属于函数内部不可见的外层变量。
cout<<"---MAIN---\n";
cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
//---MAIN---
//i: 33 a: 0 b: -10 c: 8
//i仍然保持全局变量的好性质
//a,b,c退回使用main函数中的static变量。
i += 10; other();
//---OTHER---
//i: 75 a: 6 b: 4 c: 15
//i还是老样子,abc又是other函数中的变量
return 0;
}