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