[C++] namespace 名字空間
阿新 • • 發佈:2019-01-06
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