前言:
讲作用域之前我们首先明确几个概念:
1、变量,常量,函数,类,对象都有名字,这些名字都是标识符。
2、变量和函数分声明和定义。声明可以有多次,声明是向程序表明变量的类型和名字,用extern关键字修饰。定义只能一次,为变量分配存储空间,还可赋初值。定义包含了声明。
extern int var; //仅声明
int var; //定义
int var = 1; //定义
extern int var = 1; //定义,extern不起作用
3、程序由源码到可执行文件分为编译和链接两个阶段。编译时将一个.cpp文件及相应的.h文件编译成一个obj文件,一个obj文件就是一个编译单元(也叫模块)。链接时将所有的obj文件连接成exe文件。
4、extern关键字。这个关键字用于声明变量和函数,表示其定义是在别的编译单元,在链接时访问它。
作用域是标识符在程序中的有效范围,C++语言的作用域范围如下:
1、局部作用域:对应局部变量的生命周期,局部变量的声明出现在函数体或者代码块({…},for{…},while{…},switch{…}等)中。
2、全局作用域:对应全局变量的生命周期,extern修饰的全局变量可在其他编译单元被访问,static修饰的全局变量只能在当前编译单元中被访问。
3、类作用域:类的定义范围,在同一个类的作用域中,成员函数对成员变量有无限访问权。
4、命名空间域:用于解决明明冲突,跟Java中“包”的概念类似。
接下来详细讲解这4种作用域。
正文:
1、局部作用域:位于花括号{…}内的标识符都是局部作用域,不再赘述。
2、全局作用域:这个要详细了解下。
C++可以在类的外面定义变量,这也是与Java的区别之一。全局变量的常见用法有2种,一种是在头文件(.h)中定义一个全局变量,然后在源文件(.cpp)中引用头文件即可使用该全局变量。第二种用法是头文件中的全局变量只被声明,并结合extern关键字,然后在其中一个源文件中定义该全局变量,之后在其他源文件中只需要引用头文件,就可以访问到该全局变量,代码如下:
先写头文件
/*
文件名:externHead.h
*/
#ifndef _EXTERNHEAD_H_
#define _EXTERNHEAD_H_
/*
在头文件里最好只声明,不定义,这样能避免在包含了该头文件的源文件中重复定义变量。
*/
extern char* globalVariable; //声明一个全局变量,这里仅声明,且用extern修饰。
#endif // !_EXTERNHEAD_H_
再写源文件
/*
文件名:test1.cpp
*/
#include "stdafx.h"
#include<iostream>
#include "externHead.h" //引用头文件
char* globalVariable = "i am global variable"; //定义全局变量
再写一个源文件
/*
文件名:test2.cpp
*/
#include "stdafx.h"
#include<iostream>
#include "externHead.h" //引用头文件
int main()
{
std::cout << globalVariable; //同样能访问全局变量
}
以上用法还适用于类的成员函数的声明和定义,会另开一篇文章细讲。
3、类作用域:不再赘述,参考面向对象中封装的概念。
4、命名空间作用域:将全局变量或函数放到命名空间中,可解决命名冲突问题。命名空间可以没有名字,这样可以将该命名空间中的成员的声明周期限定在本编译单元,效果与static一样。注意,同一个命名空间名可以出现在不同文件中,如下代码:
/*
文件名:externHead.h
*/
#ifndef _EXTERNHEAD_H_
#define _EXTERNHEAD_H_
namespace head {
extern char* globalVariable; //仅声明
char* globalVariable = "i am global variable"; //定义
}
#endif // !_EXTERNHEAD_H_
/*
文件名:externHead2.h
*/
#ifndef _EXTERNHEAD2_H_
#define _EXTERNHEAD2_H_
namespace head {
extern char* globalVariable2; //仅声明
char* globalVariable2 = "i am global variable, too"; //定义
}
#endif // !_EXTERNHEAD_H_
/*
文件名:test2.cpp
*/
#include "stdafx.h"
#include<iostream>
#include "externHead.h" //引用头文件
#include "externHead2.h" //引用头文件
int main()
{
std::cout << head::globalVariable; //同样能访问全局变量
std::cout << head::globalVariable2; //同样能访问全局变量
}
大家熟知的std命名空间就是这样出现在多个文件中。
总结
纯面向对象语言如Java,任何变量都是在类里面定义的。由于C++并不是完全面向对象的,还存在全局变量这么个概念。不过我们在写程序时,应尽量避免全局变量,可将其封装进类里面,并对外提供读写函数。