命名空间
命名空间的主要作用是解决命名冲突,以区分名称相同的两个变量或方法。类似于区分3班的张伟和7班的张伟,或3班的班规和7班的班规。
作用域符号"::"
说到命名空间的使用,不得不先提的一个符号"::"。
用法: 命名空间名称::变量名,命名空间名称::方法名()。
若无命名空间名称,直接写 ::a ,那么就是使用的全局变量
如果有两个同名的变量a,一个是全局变量,一个是局部变量,若无指定说明,按照就近原则,局部变量优先于全局变量。若要使用全局变量,则要在变量前加上"::"。
#include <iostream>
using namespace std;
int a=10;//全局变量
void func()
{
int a=100;//局部变量
cout<<"局部变量 a="<<a<<endl;
cout<<"全局变量 a="<<::a<<endl;
}
int main(int argc, char *argv[])
{
func();
return 0;
}
运行结果
命名空间定义
命名空间定义用关键字 namespace 来定义。
#include <iostream>
using namespace std;
int a=10;//全局变量
//定义命名空间
namespace AA{
int a= 102 ;
}
namespace BB{
int a =1002 ;
}
int main(int argc, char *argv[])
{
int a=100;//局部变量
cout<<"局部变量 a="<<a<<endl;
cout<<"全局变量 a="<<::a<<endl;
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"BB空间 a="<<BB::a<<endl;
return 0;
}
运行结果:
命名空间必须在全局范围内定义,否则编译会出错。
#include <iostream>
using namespace std;
int a=10;//全局变量
//定义命名空间
namespace AA{
int a= 102 ;
}
void func()
{
//非法的 命名空间BB
namespace BB{
int a =1002 ;
}
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"BB空间 a="<<BB::a<<endl;
}
int main(int argc, char *argv[])
{
func();
return 0;
}
编译结果:命名空间不允许定义在这里,且BB未被声明。
命名空间可以嵌套定义,BB空间生命在AA空间中。
#include <iostream>
using namespace std;
int a=10;//全局变量
//定义命名空间
namespace AA{
int a= 102 ;
namespace BB{
int a =1002 ;
}
}
int main(int argc, char *argv[])
{
int a=100;//局部变量
cout<<"局部变量 a="<<a<<endl;
cout<<"全局变量 a="<<::a<<endl;
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"BB空间 a="<<AA::BB::a<<endl;
return 0;
}
运行结果:
命名空间的开放性
命名空间成员变量和函数可以随时增加,只需要在namespace中声明即可。
调用时需声明变量及函数归属的命名空间。命名空间内可直接调用,不必声明空间名称。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
int b = 103 ;
}
//AA空间的扩展定义新成员
namespace AA{
int c=1001;
void plus(){
cout<<"This is function plus(),c="<< c <<endl;
}
void sub();
}
int main(int argc, char *argv[])
{
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"AA空间 b="<<AA::b<<endl;
cout<<"AA空间 c="<<AA::c<<endl;
AA::plus();
return 0;
}
运行结果
外部定义函数
命名空间中的函数可以在外部定义,但是一定要在内部声明。
在外部定义时,要表明其归属的命名空间。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
int b = 103 ;
}
//AA空间的扩展定义新成员
namespace AA{
int c=1001;
int d=2001;
void plus(){
cout<<"This is function plus(),c="<< c <<endl;
}
void sub();
}
//外部定义
void AA::sub(){
cout<<"This is function plus(),d="<< d <<endl;
}
int main(int argc, char *argv[])
{
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"AA空间 b="<<AA::b<<endl;
cout<<"AA空间 c="<<AA::c<<endl;
AA::plus();
AA::sub();
return 0;
}
运行结果
无名命名空间
表明此空间内的标识符只能在本文件内访问,相当于给标识符加上static。
尽量避免此类用法,以免造成歧义。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
int b = 103 ;
}
//无名的命名空间
namespace{
int n=3001 ;
}
int main(int argc, char *argv[])
{
cout<<"AA空间 a="<<AA::a<<endl;
cout<<"AA空间 b="<<AA::b<<endl;
cout<<"无名空间 n="<< n <<endl;
return 0;
}
运行结果
命名空间的别名
定义别名用namespace。用法可以理解为赋值,把原有的空间名称,赋值给新的空间名称。
意义:每次调用时不用写很长的空间前缀。
#include <iostream>
#include <file.cpp>
using namespace std;
//定义命名空间
namespace veryLongName{
int a = 102 ;
int b = 103 ;
}
int main(int argc, char *argv[])
{
namespace shortName = veryLongName;//为veryLongName起别名为shortName
cout<<"空间别名shortName调用 a="<<shortName::a<<endl;
cout<<"空间别名shortName调用 b="<<shortName::b<<endl;
return 0;
}
运行结果
using的使用
using是简化了命名空间的成员访问。使用频次高的空间成员更快捷的调用,不用每次调用都写一遍空间名称。
如果要调用其他命名空间的成员,还是要写上空间名称的。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
void func()
{
cout<<"这是AA的func()函数"<<endl;
}
}
namespace BB {
int b = 103 ;
}
void func(){
cout<<"这是普通函数func"<<endl;
}
int main(int argc, char *argv[])
{
using namespace AA ; //声明从此位置往下执行的语句优先使用AA空间的成员
int b = 100 ;
cout<<"AA空间 调用 a="<< a <<endl;
cout<<"优先调用局部变量 b="<< b <<endl;
cout<<"BB空间 调用 b="<<BB::b <<endl;
return 0;
}
运行结果
当然,在享受便捷的同时,也是有代价的,代价是容易造成冲突。
如普通函数与成员函数与命名空间中的成员函数冲突,即使声明了using namespace 也会编译出错。因为这两个函数都被认为是全局函数方法。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
void func()
{
cout<<"这是AA的func()函数"<<endl;
}
}
void func(){
cout<<"这是普通函数func"<<endl;
}
int main(int argc, char *argv[])
{
using namespace AA ;
func();
return 0;
}
编译结果
解决冲突的方法,就需要表明要调用的具体是哪个函数。使用关键字using,此时就只能调用指定的成员,其他成员则无法访问。
如下代码中,指定使用AA的func,那么命名空间中只有func()可以被访问,变量a不可被访问。变量a 会从其他地方寻找(局部变量、全局变量等)。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
void func()
{
cout<<"这是AA的func()函数"<<endl;
}
}
void func(){
cout<<"这是普通函数func"<<endl;
}
int a = 1000;
int main(int argc, char *argv[])
{
using AA::func;
func();
cout<<"a="<< a <<endl;
return 0;
}
运行结果
using直接使用命名空间中的成员会和局部变量冲突,编译会报错,提示变量已经声明过。不会和全局变量冲突,因为全局变量可以被看成 ::a。
所以要尽量避免这种情况的发生。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
}
int main(int argc, char *argv[])
{
int a = 2000;
using AA::a;
cout<<"变量 a="<< a <<endl;
return 0;
}
编译结果
解决空间成员间的二义性,就必须加作用域名称。
#include <iostream>
using namespace std;
//定义命名空间
namespace AA{
int a = 102 ;
}
namespace BB{
int a = 202 ;
}
int main(int argc, char *argv[])
{
using namespace AA;
using namespace BB;
cout<<"AA变量 a="<< AA::a <<endl;
cout<<"BB变量 a="<< BB::a <<endl;
return 0;
}
运行结果
否则编译会出错。
编译结果
总结
命名空间的定义,不能在函数内定义。
使用命名空间的成员,最准确最安全的方式 是 命名空间名称::成员名,函数不带()。
使用整个命名空间,using namespace 命名空间名称(常用)。
使用命名空间指定成员,using 命名空间名称::成员名(不常用),容易和局部变量冲突。