相信大多人在刚开始接触C++的时候,会发现几乎所有C++程序的开头都会有这么一条语句
using namespace std ;
这条语句的含义为:使用 命名空间 std
命名空间是C++引入的可以由用户命名的作用域,用来处理程序中常见的同名冲突。
在C语言中定义了3个层次的作用域:
① 文件(编译单位)
② 函数
③ 复合语句
C++中又引入了类作用域,从属于文件。在不同的作用域中可以定义相同名字的变量,互不干扰,便于系统区别它们。
同名冲突
如果在同一个程序内,取相同名字的变量会造成冲突问题。
int a = 10;
char a[10]; // 报错
那如果是两个程序中都取同一个名字的变量就不会了。
// test1.c
int a = 10;
// test2.c
int a = 20;
可如果这两个文件都被一个文件给调用的话,仍旧会出现冲突问题。
// main.c
#include "test1.h"
#include "test2.h"
int main(){
cout<<a<<endl; // 报错
}
当然,可以通过 extern 声明同一程序中的两个文件的同名变量是同一个变量
// test2.c
extern int a ;
cout<<a<<endl; // 输出的值为 10 ,即在test1中的 a 的值
但很明显,这样并不是我们想要的理想状态。
命名空间
为了解决上面的问题,C++增加了命名空间(namespace)。所谓命名空间,实际上就是一个由程序设计者命名的内存区域。程序设计者而可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来。
// test1.c
namespace n1
{
int a = 10;
}
// test2.c
namespace n2
{
int a = 20;
}
// main.c
#include "test1.h"
#include "test2.h"
int main(){
cout<<n1::a<<endl; // 10
cout<<n2::a<<endl; // 20
}
可以看到命名空间的声明方法和使用方法和类相似,但它们之间有一点差别。命名空间声明结束以后不需要加分号,而类需要。
class n1
{
};
using
在使用namespace解决了同名问题后,我们能观察到命名空间的空间成员使用方法是需要加上命名空间限定的
cout<<n1::a<<endl;
当然,我们可以使用 using 来进行声明,避免每一次使用空间成员时添加限定
using n1::a ;
cout<<a<<endl;
但如果某一个命名空间中有 n 个空间成员,那么我们需要使用 n 次 using来声明。
于是,“ using namespace 命名空间名” 应运而生
namespace n1
{
int a1 = 10;
int a2 = 20;
}
using namespace n1;
int main(){
cout<<a1<<endl;cout<<a2<<endl;
}
使用 using 让该命名空间中的任何成员都不必添加命名空间限定。
标准命名空间std
为了解决C++标准库中的标识符与程序中的全局标识符之间以及不同库中的标识符之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义(或声明)。
标准C++库的所有标识符都是在一个名为 std 的命名空间中定义的,或者说标准头文件(如iostream)中函数、类、对象和模板都是在命名空间 std 中定义的。
using namespace std;
这样,在 std 中定义和声明的所有标识符在本程序中都可以作为全局变量来使用。
参考书籍:
《C++面向对象程序设计 (第二版)》谭浩强