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