[英]“using namespace” in c++ headers
在我們所有的 c++ 課程中,所有的老師總是把using namespace std;
就在他們的.h
文件中的#include
之后。 從那時起,在我看來,通過將 header 包含在另一個程序中,這在我看來是危險的,我將把命名空間導入我的程序中,可能沒有意識到、有意或想要它(標題包含可以非常深入地嵌套)。
所以我的問題是雙重的:我是否正確不應在 header 文件中using namespace
,和/或是否有某種方法可以撤消它,例如:
//header.h
using namespace std {
.
.
.
}
One more question along the same lines: Should a header file #include
all the headers that it's corresponding .cpp
file needs, only those that are needed for the header definitions and let the .cpp
file #include
the rest, or none and declare everything它需要作為extern
?
問題背后的原因與上述相同:我不想在包含.h
文件時出現意外。
另外,如果我是對的,這是一個常見的錯誤嗎? 我的意思是在現實世界的編程和那里的“真實”項目中。
謝謝你。
由於您所說的原因,您絕對不應該在標頭中使用using namespace
,因為它可能會意外地更改包含該 header 的任何其他文件中代碼的含義。 沒有辦法撤消using namespace
,這是它如此危險的另一個原因。 我通常只使用grep
等來確保不會在標頭中調用using namespace
而不是嘗試更復雜的操作。 可能 static 代碼檢查器也會標記這一點。
header 應該只包含它需要編譯的頭文件。 執行此操作的一種簡單方法是始終將每個源文件自己的 header 作為第一件事包含在任何其他標頭之前。 如果 header 不是獨立的,則源文件將無法編譯。 在某些情況下,例如引用庫中的實現細節類,您可以使用前向聲明而不是#include
,因為您可以完全控制此類前向聲明的 class 的定義。
我不確定我是否會稱之為普通,但它肯定會偶爾出現,通常是由不知道負面后果的新程序員編寫的。 通常,只需對風險進行一點教育就可以解決任何問題,因為它相對容易修復。
Sutter 和 Alexandrescu 的“C++ 編碼標准:101 條規則、指南和最佳實踐”中的第 59 項:
59. 不要在 header 文件中或 #include 之前寫入命名空間 usings。
命名空間
using
是為了您的方便,而不是讓您強加於他人:切勿在#include
指令之前編寫using
聲明或using
指令。推論:在 header 文件中,不要編寫命名空間級別的
using
指令或using
聲明; 相反,明確命名空間限定所有名稱。
header 文件是一個或多個源文件中的來賓。 包含using
指令和聲明的 header 文件也將其吵鬧的伙伴帶到了這里。
using
聲明帶來了一個伙伴。 using
指令會引入命名空間中的所有伙伴。 您的老師對using namespace std;
是一個使用指令。
更嚴重的是,我們有命名空間來避免名稱沖突。 header 文件旨在提供接口。 大多數標頭不知道現在或將來可能包含哪些代碼。 為了內部方便,在 header 中添加using
語句會將這些方便的名稱強加給 header 的所有潛在客戶。 這可能導致名稱沖突。 這很粗魯。
關於“有什么方法可以撤消[ using
聲明]?”
我認為指出using
聲明受 scope 影響是有用的。
#include <vector>
{ // begin a new scope with {
using namespace std;
vector myVector; // std::vector is used
} // end the scope with }
vector myOtherVector; // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified
所以有效的是。 通過限制using
聲明的 scope,其效果僅在 scope 內持續; 當 scope 結束時,它被“撤消”。
當using
聲明在任何其他 scope 之外的文件中聲明時,它具有文件范圍並影響該文件中的所有內容。
對於 header 文件,如果using
聲明在文件范圍內,這將擴展到包含 header 的任何文件的 scope。
查看戈達德太空飛行中心編碼標准(C 和 C++)。 事實證明這比以前更難了 - 請參閱 SO 問題的更新答案:
GSFC C++ 編碼標准說:
§3.3.7 每個 header 文件都應
#include
它需要編譯的文件,而不是強制用戶#include
需要的文件。#includes
應限於 header 需要的內容; 其他#includes
應該放在源文件中。
交叉引用的第一個問題現在包括來自 GSFC C 編碼標准的引用,以及基本原理,但內容最終是相同的。
你是對的,在 header 中using namespace
是危險的。 我不知道如何撤消它。 很容易檢測到它,但是只需在 header 文件中搜索using namespace
。 由於最后一個原因,它在實際項目中並不常見。 如果有人做了類似的事情,更有經驗的同事很快就會抱怨。
在實際項目中,人們會盡量減少包含文件的數量,因為包含的文件越少,編譯的速度就越快。 這樣就節省了大家的時間。 但是,如果 header 文件假定應該在它之前包含某些內容,那么它應該包含它本身。 否則,它會使標頭不自包含。
你說的對。 並且任何文件都應該只包含該文件所需的標題。 至於“做錯事在現實世界的項目中很常見嗎?” - 哦是的!
就像編程中的所有事情一樣,實用主義應該戰勝教條主義,IMO。
只要您在整個項目范圍內做出決定(“我們的項目廣泛使用 STL,我們不想在所有內容前面都加上 std::.”),我看不出它有什么問題。 畢竟,您唯一冒的風險就是名稱沖突,而且隨着 STL 的普遍存在,這不太可能成為問題。
另一方面,如果這是一個開發人員在單個(非私有)頭文件中的決定,我可以看到它會如何在團隊中產生混亂,應該避免。
如果您在嵌套命名空間中編寫聲明,我相信您可以安全地在 C++ 標頭中使用“使用”:
namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED
{
/*using statements*/
namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED
{
/*declarations*/
}
}
using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED;
這應該只包括在 'DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED' 中聲明的東西,而不包括使用的命名空間。 我已經在 mingw64 編譯器上對其進行了測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.