在c++中,名稱(name)能夠是符號常量、變量、函數、結構、枚舉、類和對象等等。工程越大,名稱互相沖突性的可能性越大。另外使用多個廠商的類庫時,也可能致使名稱衝突。爲了不,在大規模程序的設計中,以及在程序員使用各類各樣的C++庫時,這些標識符的命名發生衝突,標準C++引入關鍵字namespace(命名空間/名字空間/名稱空間),能夠更好地控制標識符的做用域。c++
建立一個命名空間:程序員
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; }
命名空間可嵌套命名空間spa
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(); }
聲明和實現可分離code
#pragma once namespace 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(); }
命名空間別名blog
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聲明來消除名字衝突,這樣不須要修改其餘的實現文件。