C 中的名字空間

2021-09-26 02:04:31 字數 4265 閱讀 6908

摘抄自《c++ primer plus》

在c++中,名稱可以是變數、函式、結構、列舉、類以及類和結構的成員。當隨著專案的增大,名稱相互衝突的可能性也將增加。使用多個廠商的類庫時,可能導致名稱衝突。例如,兩個庫可能都定義了名為list、tree和node的類,但定義的方式不相容。使用者可能希望使用乙個庫的list類,而使用另乙個庫的tree類。這種衝突被稱為命名空間問題

c++標準提供了命名空間工具,以便更好地控制名稱的作用域。經過了一段時間後,編譯器才支援命名空間,但現在這種支援很普遍。

先來明白幾個術語

然而,變數並非在其潛在作用域內的任何位置都是可見的。例如,它可能被另乙個在巢狀宣告區域中宣告的同名變數隱藏。例如,在函式中宣告的區域性變數(對於這種變數,宣告區域為整個函式)將隱藏在同乙個檔案中宣告的全域性變數(對於這種變數,宣告區域為整個檔案)。變數對程式而言可見的範圍被稱為作用域(scope),前面正是以這種方式使用該術語的。

c++的傳統命名空間和c中的一樣

c++新增了這樣一種功能,即通過定義一種新的宣告區域來建立命名的命名空間,這樣做的目的之一是提供乙個宣告名稱的區域。乙個命名空間中的名稱不會與另外乙個命名空間的相同名稱發生衝突,同時允許程式的其他部分使用該命名空間中宣告的東西。例如,下面的**使用新的關鍵字namespace建立了兩個命名空間:jack和jill。

namespace jack

namespace jill

任何命名空間中的名稱都不會與其他命名空間中的名稱發生衝突。因此,jack中的fetch可以與jill中的fetch共存,jill中的hill可以與外部hill共存。命名空間中的宣告和定義規則同全域性宣告和定義規則相同。

原來的jack命名空間為fetch( )函式提供了原型。可以在該檔案後面(或另外乙個檔案中)再次使用jack命名空間來提供該函式的**:

namespace jack

}

當然,需要有一種方法來訪問給定命名空間中的名稱。最簡單的方法是,通過作用域解析運算子::,使用命名空間來限定該名稱:

jack:

:pail =

12.34

;jill:

:hill mole;

jack:

:fetch()

;

未被裝飾的名稱(如pail)稱為未限定的名稱(unqualified name);包含命名空間的名稱(如jack::pail)稱為限定的名稱(qualified name)我們並不希望每次使用名稱時都對它進行限定,因此c++提供了兩種機制(using宣告和using編譯指令)來簡化對命名空間中名稱的使用。using宣告使特定的識別符號可用,using編譯指令使整個命名空間可用。

using宣告由被限定的名稱和它前面的關鍵字using組成:

using jill:

:fetch //a using declaration

完成該宣告後,便可用fetch代替jill::fetch

using宣告使乙個名稱可用,而using編譯指令使所有的名稱都可用。using編譯指令由命名空間名和它前面的關鍵字using namespace組成,它使命名空間中的所有名稱都可用,而不需要使用作用域解析運算子:

using namespace jack;
使用using宣告和using編譯指令將增加名稱衝突的可能性,如下所示:

using jack:

:pal;

using jill:

:pal;

pal =

4;

pal到底是哪乙個呢?這裡便發生了衝突。

使用using編譯指令匯入乙個命名空間中所有的名稱與使用多個using宣告是不一樣的,而更像是大量使用作用域解析運算子。使用 using 宣告時,就好像宣告了相應的名稱一樣。如果某個名稱已經在函式中宣告了,則不能用using宣告匯入相同的名稱。然而,使用using編譯指令時,將進行名稱解析,就像在包含 using 宣告和命名空間本身的最小宣告區域中宣告了名稱一樣。在下面的示例中,命名空間為全域性的。如果使用 using 編譯指令匯入乙個已經在函式中宣告的名稱,則區域性名稱將隱藏命名空間名,就像隱藏同名的全域性變數一樣。不過仍可以像下面的示例中那樣使用作用域解析運算子

namespace jill

double fetch;

struct hill ;}

char fetch;

intmain()

一般說來,使用using宣告比使用using編譯指令更安全,這是由於它只匯入指定的名稱。如果該名稱與區域性名稱發生衝突,編譯器將發出指示。using編譯指令匯入所有名稱,包括可能並不需要的名稱。如果與區域性名稱發生衝突,則區域性名稱將覆蓋命名空間版本,而編譯器並不會發出警告。另外,命名空間的開放性意味著命名空間的名稱可能分散在多個地方,這使得難以準確知道新增了哪些名稱。

using namespace std;
而應當這樣做:

int x;

std:

:cin >> x;

std:

:cout << x << std:

:endl;

或者這樣做

using std:

:cin;

using std:

:cout;

using std:

:endl;

int x;

cin >> x;

cout << x << endl;

可以通過省略命名空間的名稱來建立未命名的命名空間:

namespace ice
這就像後面跟著using編譯指令一樣,也就是說,在該命名空間中宣告的名稱的潛在作用域為:從宣告點到該宣告區域末尾。從這個方面看,它們與全域性變數相似。然而,由於這種命名空間沒有名稱,因此不能顯式地使用using編譯指令或using宣告來使它在其他位置都可用。具體地說,不能在未命名命名空間所屬檔案之外的其他檔案中,使用該命名空間中的名稱。這提供了鏈結性為內部的靜態變數的替代品。比如下面的**:

static

int counts;

//靜態儲存,內部鏈結

intmain()

採用命名空間的方法如下:

namespace 

intmain()

現在來看乙個多檔案示例,該示例說明了命名空間的一些特性。

第乙個檔案是標頭檔案:

#include

namespace pers

;void

getperson

(person &);

void

showperson

(const person &);

}namespace debts

;void

getdebt

(debt &);

void

showdebt

(const debt &);

double

sumdebts

(const debt ar,

int n)

;}

第二個是原始碼檔案,它提供了標頭檔案中函式原型對應的定義。

#include

#include

"namesp.h"

namespace pers

void

showperson

(const person &rp)

}namespace debts

void

showdebt

(const debt &rd)

double

sumdebts

(const debts ar,

int n)

}

隨著程式設計師逐漸熟悉命名空間,將出現統一的程式設計理念。下面是當前的一些指導原則。

C 的名字空間

1 名字空間的作用 1 避免名字衝突 2 劃分邏輯單元 2 定義名字空間 namespace 名字空間 struct student namespace ns2 3 名字空間成員的使用 1 通過作用域限定操作 空間成員 要訪問的成員 eg int main void 02namespace.cpp ...

C 的名字空間

名字空間主要用於解決名字衝突的問題,應用程式可能會呼叫多個庫程式,不同的庫程式可能會存在相同 的全域性變數名,全域性函式名,類名等。庫程式的作者為了避免其他程式中名字或者使用者自己定義的名字衝突,將庫程式中的所有名字放在乙個特定的名字空間下。這樣乙個識別符號可以在不同的名字空間使用,提高標識 符的利...

C 名字空間

namespace 名字空間名 注 名字空間成員可以是全域性變數 全域性函式 型別 名字空間 作用域限定操作符 名字空間名 要訪問的成員 include namespace nm1 namespace nm2 intmain 當名字沒有重複的時候,我們可以簡化 方法一 名字空間指令 格式 using...