1. 程式人生 > >[C++] namespace 名字空間

[C++] namespace 名字空間

1. 使用名字空間是為了避免命名衝突。名字空間的定義,關鍵字namespace + 名字 + {...}, 後面不加分號,如果名字省略,則為未命名的名字空間。std即為最常見的名字空間,namespace 可以加在標頭檔案和原始檔中,namespace定義可以合併寫,也可以分散寫。

// ---- Sales_item.h ----
namespace cplusplus_primer {
    class Sales_item { /* ... */};
    Sales_item operator+(const Sales_item&, const Sales_item&);
    // declarations for remaining functions in the Sales_item interface
}

// ---- Query.h ----
namespace cplusplus_primer {
    class Query {
    public:
        Query(const std::string&);
    std::ostream &display(std::ostream&) const;
    // ...
    };
    class Query_base { /* ... */};
} 

// ---- Sales_item.cc ----
#include "Sales_item.h"
namespace cplusplus_primer {
    // definitions for Sales_item members and overloaded operators
}

// ---- Query.cc ----
#include "Query.h"
namespace cplusplus_primer {
    // definitions for Query members and related functions
}

2. namespace 可以巢狀:

namespace cplusplus_primer {
    // first nested namespace:
    // defines the Query portion of the library
    namespace QueryLib {
        class Query { /* ... */ };
        Query operator&(const Query&, const Query&);
        // ...
    }
    // second nested namespace:
    // defines the Sales_item portion of the library
    namespace Bookstore {
        class Item_base { /* ... */ };
        class Bulk_item : public Item_base { /* ... */ };
        // ...
    }
}
// Query 類名變為:cplusplus_primer::QueryLib::Query

3. 要儘量使用using宣告(using declaration),例如:using std::vector, 避免使用 using 指示 (using directive),例如:using namespace std; 後者有可能會導致命名衝突。

假定 A 和 f 都在全域性域內,在函式f內使用 using namespace 會使得變數 i 和 j也全域性域內:

    // namespace A and function f are defined at global scope
    namespace A {
        int i, j;
    }
    void f()
    {
        using namespace A;      // injects names from A into the global scope
        cout << i * j << endl; // uses i and j from namespace A
        //...
    }


4. 可以用名字空間別名簡化一連串的名字空間,例如:

namespace primer = cplusplus_primer;
namespace Qlib = cplusplus_primer::QueryLib;
Qlib::Query tq;
5. 如果一個函式(包括過載操作符)的形參是一個類(或類引用的指標), 而函式和類在同一個名字空間,那麼,當類的物件, 引用,或指標作為實參時,函式可見,因此,下面的getline 函式前面不需要加 std。
std::string s;
// ok: calls std::getline(std::istream&, const std::string&)
getline(std::cin, s);

6. 名字空間內變數的查詢,和函式內部變數查詢過程類似:

 namespace A {
        int i;
        namespace B {
            int i;        // hides A::i within B
            int j;
            int f1()
            {
                int j;    // j is local to f1 and hides A::B::j
                return i; // returns B::i
            }
        } // namespace B is closed and names in it are no longer visible
        int f2() {
           return j;     // error: j is not defined
        }
        int j = i;      // initialized from A::i
 }
namespace A {
        int i;
        int k;
        class C1 {
        public:
            C1(): i(0), j(0) { }   // ok: initializes C1::i and C1::j
            int f1()
            {
                 return k;        // returns A::k
            }
            int f2()
            {
                return h;        // error: h is not defined
            }
            int f3();
        private:
           int i;                // hides A::i within C1
           int j;
        };
        int h = i;               // initialized from A::i
}
// member f3 is defined outside class C1 and outside namespace A
int A::C1::f3()
{
    return h;               // ok: returns A::h
}

7.  過載函式和using 宣告, 不能指定具體的函式,using NS:print 可以使所有的過載函式print可見:

using NS::print(int); // error: cannot specify parameter list
using NS::print;      // ok: using declarations specify names only

8.  未命名的名字空間使定義內容只對該檔案可見,各個檔案中定義的unnamed namespace相互獨立,應該用unnamed namespace 取代使用static宣告,使名字只local可見的做法。

C++ Primer 17.2 Namespaces