名字控制
创建名字是程序设计过程中一项最基本的活动,当一个项目很大时,它会不可避免地包含大量名字。C++允许我们对名字的产生和名字的可见性进行控制。我们在学习C语言可以通过static关键字来使得名字智能在本编译单元内可见,在C++中我们通过一个通过命名空间来控制对名字的访问。
 
命名空间namespace
在C++中,名称(name)可以时符号常量、变量、函数、结构、美剧、类和对象等等。工程越大,名称互相重冲突可能越大。另外使用多个厂商的类库时,也是可能导致名称冲入。为了避免,在大型程序开发中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namespace,可以更好地控制标识符的作用域。
 
1、作用:尽最大可能解决命名冲突
命名空间的使用语法

namespace A {
 int a =10;
 }
 namespace B {
 int a =20;
 }
 void test()
 {
 cout<<“A:🅰️”<<A::a<<endl;
 cout<<“B:🅰️”<<B::a<<endl;
 }
 int main()
 {
 cout << “这是一个测试程序” << endl;
 test();
 return 0;
 }


 
2、命名空间只能在全局范围内定义(以下错误的写法)

void test()
 {
 namespace A { int a =10;}
 namespace B {int a =20;}
 cout<<“A:🅰️”<<A::a<<endl;
 cout<<“B:🅰️”<<B::a<<endl;
 }


3、命名空间可嵌套命名空间

namespace A {
 int a =1000;
 namespace B {int a =2000;}
 }
 cout<<“A:🅰️”<<A::a<<endl;
 cout<<“A:🅰️”<<A::B::a<<endl;


 
4、命名空间时开放的,即可以随时把新成员加入到已有的成员。(常用功能)

namespace A { int a =10;b=100}
 namespace A { int c=300;}//意思时把变量c=300加入到namespace A中。


 
5、命名空间也可以存放函数(因为C++封装就是把数据和方法封装到一个对象里面)

namespace A
 {
 int a =10;
 void func()
 {cout<<“a:”<<a<<endl;//同属于一个命名空间可以不用加域运算符 }
 }
 void test()
 {
 cout<<“A:🅰️”<<A::a<<endl;
 cout<<“A::func():”<<A::func()<<endl; //调用命名空间里面的函数也需要声明作用域于A
 }

6、命名空间中的函数可以在外面定义

void A::func()//在外部定义函数的时候需要加作用域
 { cout<<“a:”<<a<<endl;//调用内部数据及函数不需要作用域
 namespace A
 {
 int a =10;
 void func() ;//命名空间内部声明,外部定义}
 }


 
以下为错误的方法:

void func(){ cout<<“a:”<<a<<endl;//方法缺省作用域}
 namespace A
 { int a =10; void func(); }


 
7、无名的命名空间----表示本命名空间只能在本文件使用和static作用一样,尽量少定义

namespace {int a =10; void func(); }


 
8、命名空间 取别名 赋值语句 别名和旧名字都可以同时使用(极少使用)

namespace old_name
 namespace old_name = new_name;


 
9、【using】使用命名空间 会从命名空间中找 找不到 其他地方中找
a、简化了从命名空间找数据

void test()
 {
 //使用veryLongName
 using namespace veryLongName;
 //出现的变量 会从veryLongName命名空间中找 找不到 其他地方中找
 cout<<“A::veryLongName:”<<a<<endl;
 }


b、代价(容易造成冲突)保持就近原则

namespace veryLongName{ int a=200;func() { cout<<“veryLongName”<<endl;}}
 void test()
 {
 int a=100;
 //使用veryLongName
 using namespace veryLongName;
 cout<<“输出a:”<<a<<//endl;保持就近原则
 cout<<“输出a:”<<veryLongName::a<<endl;
 }


c、指明使用命名空间的具体成员

namespace veryLongName{ int a=200;func() { cout<<“veryLongName”<<endl;}}
 void test()
 {
 using namespace veryLongName::a;
 cout<<“输出a:”<<a<<endl;//这里是正常输出,不会报错
 func(); //这里会报错
 veryLongName::func(); //这里是正常输出,不会报错
 }


d、直接使用using 如果和当前方法冲突会报错,但是不会和全局变量冲突

void test()
 {
 int a = 200;
 using namespace veryLongName::a;
 cout<<“输出a:”<<a<<endl;
 func();
 }


e、【using】 遇到重载函数时 指明 会话 所有的重载方法起作用

namespace A{
 //func_void
 func() { cout<<“无参的func”<<endl;}
 //func_int
 func(int a) { cout<<“int a 的func”<<endl;}
 //func_int_int
 func(int a ,int b) { cout<<“int a ,int a 的func”<<endl;}
 }
 void test()
 { using A::func; //using指明 使用 A中的func 会话 所有的func起作用
 func() ;func(10) ;func(10,20) ;//所有的func起作用}


 
10、【using】编译指令 如果使用整个命名空间,所有成员都可以正常访问

namespace A{
 int a=100;
 //func_void
 func() { cout<<“无参的func”<<endl;}
 //func_int
 func(int a) { cout<<“int a 的func”<<endl;}
 //func_int_int
 func(int a ,int b) { cout<<“int a ,int a 的func”<<endl;}
 }
 void test()
 { using A; //using使用整个命名空间
 func() ;func(10) ;func(10,20) ;//所有的func起作用
 cout<<“A中的a:”<<a<<endl;//如果使用整个命名空间,所有成员都可以正常访问
 }


 
11、多个命名空间使用同名成员 产生二义性 需要加作用域
 
总结:
1、命名空间的定义(不能在 函数内定义命名空间)
2、使用命名空间的成员 最安全的方式 命名空间名::成员名
3、using namespace 命名空间名;使用这个命名空间
using namespace A;
4、单独 使用命名空间成员中的具体成员: using 命名空间名:成员名
using namespaceA::a;