传统的C++名称空间
先说以下三个基本概念:声明区域,潜在作用域,作用域。
声明区域:即变量可以声明的区域。如全局变量的声明区域就是全局的,代码块里的变量的声明区域就是该代码块。
潜在作用域:在该变量的声明区域中,从该变量声明的位置起,到声明区域结束,都是该变量的潜在作用域。
作用域:变量并非在其潜在作用域的所有地方都可见,比如会被另一个被嵌套的代码块中的同名变量给覆盖掉。因此,变量可见的范围是作用域。
通常:声明区域>潜在作用域>作用域。
新的名称空间的特性
可通过定义新的名称区域来创建命名的名称空间。两个名称空间中的同名变量不会发生冲突。 名称空间只能声明在全局。
#include<iostream>
#include<cstdio>
using namespace std;
namespace space1 //定义了两个名称空间,名称空间可以是全局的,也可以位于另一个名称空间中,
{ //但不能位于代码块中,因此默认情况下,名称空间声明的名称链接性是外部的。
int a, b;
void fun();
}
namespace space2
{
int a, b;
void fun();
}
int main()
{
space1::a = 1; //可以通过作用域解析符::来使用名称空间限定该名称。
space2::a = 2;
return 0;
}
using声明和using编译指令:
using声明将特定的名称添加到它所属的声明区域中。完成该声明后,便不再需要作用域解析符来指定特定的名称空间。
而using编译指令使名称空间中的所有名称都可用。
using namespace space2; //space2中所有的名称都可用
int main()
{
using space1::a; //只能不加修饰地用space1中的a,注意同其他变量一样,space1的a会覆盖掉全局的space2的a
a = 1; //但如果这里是using namespace space1,编译不能通过,因为无法区分这是哪一个a
cout << a << endl;
return 0;
}
凡是会导致二义性的,编译都不能通过。二义性指编译器不知道该怎么做。
using编译指令和using声明的比较:
using声明更像是定义了某个变量,因此在局部中,如果已经定义了一个局部变量,这时候再用using导入同名的名称,则会产生二义性,编译出错。而用using编译指令,则不会报错。并且局部变量会覆盖掉名称空间的同名变量,而不管它们的先后顺序。
int a;
using space1::a; //编译会出错
int a;
using namespace space1;
a = 1;
cout << a << endl; //输出1
cout << space1::a << endl; //输出0
//说明局部变量a会覆盖掉名称空间space1中的a,而无论它们的声明顺序如何,space1中的同名变量总是会被覆盖
名称空间的其他特性:
名称空间可以嵌套
namespace space1
{
int a, b;
namespace space2 //这里的c指的是space1::space2::c,同样可以用using编译指令使内部的名称空间可用
{ //using namespace space1::space2;
int c, d; //对于嵌套的名称空间,using namespace space1将同时导入space1和space2。
}
}
另外还可以在名称空间中使用using编译指令和using声明。
namespace space3
{
using space1::a; //因此如果要访问a,可以space1::a,也可以space3::a。
using namespace space2;
using std::cout;
} //在没有同名的局部变量的情况下,使用using namespace space3之后,也可以不加限定名地访问a。
还可以给名称空间创建别名。
namespace space1
{
int a, b;
}
namespace t = space1; //这时候t和space1是等价的
int main()
{
space1::a = 1;
cout << t::a << endl;
return 0;
}
未命名的名称空间:
可以通过省略名称空间的名称来创建未命名的名称空间。
namespace
{
int a, b;
}
这就像后面跟着using编译指令一样。即该名称空间的潜在作用域是从声明点到起声明区域为止。类似于全局变量。由于没有名字,因此不能在别的地方使用using来导入该名称空间和其中的变量。这效果就像链接性为内部的静态变量。
namespace //static int a; 效果是一样的
{
int a;
}
名称空间示例:
head.h:
namespace space1
{
int a, b;
using namespace std;
void show()
{
cout << a << endl << b << endl;
}
}
源文件:
#include<iostream>
#include<cstdio>
#include"head.h"
using namespace space1;
int main()
{
a = 1;
b = 2;
show();
return 0;
}