[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

猜你喜欢

转载自blog.csdn.net/ftell/article/details/80020632
今日推荐