C++命名空間(namespace)


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 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();
}

 

命名空間別名

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聲明來消除名字沖突,這樣不需要修改其他的實現文件。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM