簡體   English   中英

c++ 標頭中的“使用命名空間”

[英]“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 的所有潛在客戶。 這可能導致名稱沖突。 這很粗魯。

在標題中包含標題時需要小心。 在大型項目中,它可以創建一個非常復雜的依賴鏈,觸發比實際需要的更大/更長的重建。 查看這篇文章及其后續文章,了解更多關於良好物理結構在 C++ 項目中的重要性。

您應該僅在絕對需要時(只要需要 class 的完整定義時)在 header 中包含標頭,並盡可能使用前向聲明(當需要 class 時是指針或引用時)。

至於命名空間,我傾向於在我的 header 文件中使用顯式命名空間范圍,並且只在我的 cpp 文件中放置一個using namespace

關於“有什么方法可以撤消[ 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM