What is a namespace?ios
A namespace defines an area of code in which all identifiers are guaranteed to be unique. By default, all variables and functions are defined in the global namespace. For example, take a look at the following snippet:app
1
2
3
4
5
|
int
nX = 5;
int
foo(
int
nX)
{
return
-nX;
}
|
Both nX and foo() are defined in the global namespace.ide
Namespaces allow to group entities like classes, objects and functions under a name. This way the global scope can be divided in "sub-scopes", each one with its own name.函數
命名空間把對象,函數,變量等分組,而後有一個名字。
The format of namespaces is:
namespace identifier
{
entities
}
Where identifier is any valid identifier and entities is the set of classes, objects and functions that are included within the namespace. For example:this
實體能夠是任何有效的標識符。spa
namespace myNamespace { int a, b; }
In this case, the variables a and b are normal variables declared within a namespace called myNamespace. In order to access these variables from outside the myNamespace namespace we have to use the scope operator ::. For example, to access the previous variables from outside myNamespace we can write:
code
1 |
myNamespace::a myNamespace::b |
The functionality of namespaces is especially useful in the case that there is a possibility that a global object or function uses the same identifier as another one, causing redefinition errors. For example:orm
// namespaces #include <iostream> using namespace std; namespace first { int var = 5; } namespace second { double var = 3.1416; } int main () { cout << first::var << endl; cout << second::var << endl; return 0; }
n this case, there are two global variables with the same name: var. One is defined within the namespace firstand the other one in second. No redefinition errors happen thanks to namespaces.
對象
The keyword using is used to introduce a name from a namespace into the current declarative region. For example:blog
#include <iostream> using namespace std; namespace first { int x = 5; int y = 10; } namespace second { double x = 3.1416; double y = 2.7183; } int main () { using first::x; using second::y; cout << x << endl; cout << y << endl; cout << first::y << endl; cout << second::x << endl; return 0; }
5 2.7183 10 3.1416Notice how in this code, x (without any name qualifier) refers to first::x whereas y refers to second::y, exactly as our using declarations have specified. We still have access to first::y and second::x using their fully qualified names.
The keyword using can also be used as a directive to introduce an entire namespace:using能夠引入整個namespace。
// using #include <iostream> using namespace std; namespace first { int x = 5; int y = 10; } namespace second { double x = 3.1416; double y = 2.7183; } int main () { using namespace first; cout << x << endl; cout << y << endl; cout << second::x << endl; cout << second::y << endl; return 0; }
In this case, since we have declared that we were using namespace first, all direct uses of x and y without name qualifiers were referring to their declarations in namespace first.
using and using namespace have validity only in the same block in which they are stated or in the entire code if they are used directly in the global scope. For example, if we had the intention to first use the objects of one namespace and then those of another one,
using 和using namespace 僅僅在他們聲明的代碼塊有效,若是在全局做用域中直接使用,則在整個代碼塊中有效。
we could do something like:
// using namespace example #include <iostream> using namespace std; namespace first { int x = 5; } namespace second { double x = 3.1416; } int main () { { using namespace first; cout << x << endl; } {2 using namespace second; cout << x << endl; } return 0; }
5 3.1416
We can declare alternate names for existing namespaces according to the following format:
namespace new_name = current_name;命名空間裏的變量衝突:
#include<iostream> using namespace std; int x=1; int y=2; namespace first { int var=5; int x=5; int y=10; } namespace second { double var=3.1416; double x=5.5; double y=10.5; } int main() { using namespace first; cout<<x<<endl; x顯示衝突 }
命名空間嵌套:
C++ does not allow compound names for namespaces.
// pluslang_namespace.cpp // compile with: /c // OK namespace a { namespace b { int i; } } // not allowed namespace c::d { // C2653 int i; }
下面的代碼嵌套命名空間;
#include<iostream> using namespace std; namespace A { void fun1(){ cout<<"fun1"<<endl; } namespace B { int a=1; void fun1(){ cout<<"b fun1"<<endl;} } } int main() { using namespace A; fun1(); //print fun1 B::fun1(); //print b fun1 }
咱們也能夠用;
A::fun1();
A::B::fun1();
結果同樣。(某個名字在本身的空間以外使用,在反覆地在前面加上名字空間做爲限定詞)
無名名字空間,無名名字空間主要是保持代碼的局部性,使用以下:
namespace
{
const int CVAR1 = 1;
void test();
}
因爲該命名空間沒有名字,不能被外部範圍。(有什麼用,咱們能夠
但必定要注意的一點是,在C++編譯器實現時,無名名字空間實際上是有名字的,這個隱含的名字跟它所在編譯單元名字相關。因此基於這一點,咱們不能跨編譯單元使用無名名字空間中的名字。
上面的聲明等價於
namespace $$$ { const int CVAR1 = 1; void test(); } using namespace $$$;
其中$$$在其所在的做用域裏具備唯一性的名字,每一個編譯單元裏的無名名字空間也是互不相同的,using namesapce $$$只是當前的編譯單元的隱含名字,因此不能跨編譯單元使用無名名字空間中的名字。
假設上面的test方法在是a.h與a.cpp中定義與實現的,但在b.h或b.cpp中就不能直接使用test方法或CVAR1。由於在b的這個編譯單元中連接的是b這個編譯單元中的test符號,並不是a編譯單元中的test符號,也就會出現未定符號。
要避免名字空間使用很短的名字,也不能太長,更不能嵌套太深了,我的以爲不要超過4層。
命名空間能夠是不連續的
一個命名空間能夠分散定義在多個文件中。不過,若是命名空間的一個部分須要使用一個定義在另外一文件中的名字,必須聲明該名字。
namespace namespace_name {
// declarations
}
若是namespace_name不是引用前面定義的命名空間,則用該名字建立新的命名空間,不然,這個定義打開一個已存在的命名空間,並將新聲明加到那個命名空間。
接口和實現的分離
能夠用分離的接口文件和實現文件構成命名空間。能夠用與管理類和函數定義相同的方法來組織命名空間。定義多個不相關類型的命名空間應該使用分離的文件分別定義每一個類型。
// sales_item.h namespace cplusplus_primer { class SalesItem { /* … */ }; SalesItem operator+(const SalesItem&, const SalesItem&); } // query.h namespace cplusplus_primer { class Query { public: Query(const std::string&); std::ostream & display(std::ostream&) const; }; } // sales_item.cpp #include 「sales_item.h」 namespace cplusplus_primer { // definitions for SalesItem members and overloaded operators } // query.cpp #include 「query.h」 namespace cplusplus_primer { // definitions for Query members and related functions }
示例:
namespace C //命名空間不連續1.h { class A { private: int a,b; public: void func(); }; }
#include"命名空間不連續1.h" #include<iostream> using namespace std; namespace C { void A::func() { a=1,b=2; cout<<a<<b<<endl; cout<<"fun1"<<endl; } } int main() { using namespace C; A a; a.func(); }
定義命名空間成員
能夠在命名空間定義的外部定義命名空間成員,相似於在類外部定義類成員的方式。
// namespace members defined outside the namespace must use qualified names cplusplus_primer::operator+(const SalesItem&, const SalesItem&) { SalesItem ret(lhs); // … }