在c++中,名稱(name)可以是符號常量、變量、函數、結構、枚舉、類和對象等等。工程越大,名稱互相沖突性的可能性越大。另外使用多個廠商的類庫時,也可能導致名稱沖突。為了避免,在大規模程序的設計中,以及在程序員使用各種各樣的C++庫時,這些標識符的命名發生沖突,標準C++引入關鍵字namespace(命名空間/名字空間/名稱空間),可以更好地控制標識符的作用域。
?
創建一個命名空間:
namespace A{int a = 10; } namespace B{int a = 20; } void test(){cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl; }
?
命名空間只能全局范圍內定義(以下錯誤寫法)
void test(){namespace A{int a = 10;}namespace B{int a = 20;}cout << "A::a : " << A::a << endl;cout << "B::a : " << B::a << endl; }
?
命名空間可嵌套命名空間
namespace A{int a = 10;namespace B{int a = 20;} } void test(){cout << "A::a : " << A::a << endl;cout << "A::B::a : " << A::B::a << endl; }
?
命名空間是開放的,即可以隨時把新的成員加入已有的命名空間中
namespace A{int a = 10; }namespace A{void func(){cout << "hello namespace!" << endl;} }void test(){cout << "A::a : " << A::a << endl;A::func(); }
?
聲明和實現可分離
?
#pragma oncenamespace MySpace{void func1();void func2(int param); }
?
void MySpace::func1(){cout << "MySpace::func1" << endl; } void MySpace::func2(int param){cout << "MySpace::func2 : " << param << endl; }
?
無名命名空間,意味著命名空間中的標識符只能在本文件內訪問,相當于給這個標識符加上了static,使得其可以作為內部連接
namespace{int a = 10;void func(){ cout << "hello namespace" << endl; } } void test(){cout << "a : " << a << endl;func(); }
?
命名空間別名
namespace veryLongName{int a = 10;void func(){ cout << "hello namespace" << endl; } }void test(){namespace shortName = veryLongName;cout << "veryLongName::a : " << shortName::a << endl;veryLongName::func();shortName::func(); }
?
------------------------------------------------------------------------------------------------------------------------------------------------------------
using聲明
using聲明可使得指定的標識符可用。
namespace A{int paramA = 20;int paramB = 30;void funcA(){ cout << "hello funcA" << endl; }void funcB(){ cout << "hello funcA" << endl; } }void test(){//1. 通過命名空間域運算符cout << A::paramA << endl;A::funcA();//2. using聲明using A::paramA;using A::funcA;cout << paramA << endl;//cout << paramB << endl; //不可直接訪問 funcA();//3. 同名沖突//int paramA = 20; //相同作用域注意同名沖突 }
using聲明碰到函數重載? ? ?
如果命名空間包含一組用相同名字重載的函數,using聲明就聲明了這個重載函數的所有集合。
1 namespace A{ 2 void func(){} 3 void func(int x){} 4 int func(int x,int y){return x+y;} 5 } 6 void test(){ 7 using A::func; 8 func(); 9 func(10); 10 func(10, 20); 11 }
?--------------------------------------------------------------------------------------------------------------
using編譯指令
?
using編譯指令使整個命名空間標識符可用.
?注意:使用using聲明或using編譯指令會增加命名沖突的可能性。也就是說,如果有名稱空間,并在代碼中使用作用域解析運算符,則不會出現二義性。
namespace A{int paramA = 20;int paramB = 30;void funcA(){ cout << "hello funcA" << endl; }void funcB(){ cout << "hello funcB" << endl; } }void test01(){using namespace A;cout << paramA << endl;cout << paramB << endl;funcA();funcB();//不會產生二義性int paramA = 30;cout << paramA << endl; }namespace B{int paramA = 20;int paramB = 30;void funcA(){ cout << "hello funcA" << endl; }void funcB(){ cout << "hello funcB" << endl; } }void test02(){using namespace A;using namespace B;//二義性產生,不知道調用A還是B的paramA//cout << paramA << endl; }
?
?
?
命名空間使用
需要記住的關鍵問題是當引入一個全局的using編譯指令時,就為該文件打開了該命名空間,它不會影響任何其他的文件,所以可以在每一個實現文件中調整對命名空間的控制。
比如,如果發現某一個實現文件中有太多的using指令而產生的命名沖突,就要對該文件做個簡單的改變,通過明確的限定或者using聲明來消除名字沖突,這樣不需要修改其他的實現文件。
?