2008-10-21 112 views
80

我在C++中使用'using'聲明將std :: string和std :: vector添加到本地命名空間(以節省鍵入不必要的'std ::'s)。C++中「using」聲明的範圍是什麼?

using std::string; 
using std::vector; 

class Foo { /*...*/ }; 

這個聲明的範圍是什麼?如果我在標題中這樣做,它是否會將這些「使用」聲明注入到包含標題的每個cpp文件中?

+17

只是爲了防止其他答案在這裏清楚: - **不要在包含文件/頭文件中的文件範圍使用`using`聲明(或`using`指令)**這將爲標題的用戶造成頭痛。 – 2008-10-21 19:07:07

+0

事實上,不要在頭文件**中使用`using`聲明(即*指令*),即使在命名空間內也是如此!*請參閱[在命名空間內使用聲明的範圍](http:/ /stackoverflow.com/q/6175705/2025416)以解決這些問題。 – 2016-05-22 15:07:04

回答

53

當您在C++中包含頭文件時,它會將頭文件的全部內容放入您將其包含在源文件中的位置。因此,包含具有using聲明的文件具有將using聲明放在包含該頭文件的每個文件頂部的效果。

+43

...這通常是一件壞事。 – Catskul 2011-02-16 05:25:13

+13

但是,如果你把`using`聲明放在`namespace`裏面,它就侷限於那個命名空間的範圍,所以一般都可以(對你的特定需求和風格有通常的注意事項)。 – Zero 2012-12-04 23:09:39

+1

......但是如果你確實在命名空間中使用了內部命令空間,請確保你沒有試圖繞過通常是個壞主意的東西,就像你不能在外部命名空間Y中聲明的類方法一樣。其他命名空間X,只是這樣你纔可以在本地使用命名空間X.這就是爲什麼我們首先使用namespace :: resolvers。如果它的鍵入問題很大,或者是一個宏(它可能很容易導致代碼味道)或者更好,將它分離到它自己的源代碼.cpp中,您將只在那裏使用名稱空間。 – osirisgothra 2014-01-17 17:29:14

5

在引用的情況下,文件(「翻譯單元」)意味着是包含它的每個文件。

您還可以將using語句放在類中,在這種情況下,它僅適用於該類。

通常,如果您需要在標頭中指定一個名稱空間,通常最好是對所需的每個標識符進行完全限定。

+0

請注意,類中的`using`聲明的行爲方式與類之外的行爲不同 - 例如,您不能使用它將`cout`而不是`std :: cout`帶入類的範圍。 – Zero 2012-12-04 23:07:32

2

這是正確的。範圍是使用using聲明的模塊。如果模塊包含的任何頭文件都有聲明,則這些聲明的範圍將是該模塊以及包含相同頭文件的任何其他模塊。

86

沒有什麼特別的頭文件可以保持using聲明。在編譯甚至開始之前,這是一個簡單的文本替換。

您可以限制using聲明的範圍:

void myFunction() 
{ 
    using namespace std; // only applies to the function's scope 
    vector<int> myVector; 
} 
+8

我從來沒有想過我可以在一個函數內使用它! – Agostino 2015-03-04 22:50:35

4

範圍是什麼範圍使用的聲明是在

如果這是全球範圍內,那麼這將是在全球範圍內傳播。如果它位於頭文件的全局範圍內,那麼它將位於包含頭的每個源文件的全局範圍內。

所以,一般的建議是避免在全局範圍內使用聲明頭文件

44

using語句的範圍取決於它位於代碼:

  • 放置在文件的頂部,它在整個這個文件的範圍。
  • 如果這是一個頭文件,它將在包含該頭的所有文件中都有作用域。在一般情況下,這是「不是一個好主意」,因爲它可以有意想不到的副作用
  • 否則使用語句包含它從它發生在塊的結束點塊內的範圍。如果它放在方法中,它將在該方法中有作用域。如果它放在類定義中,它將在該類中有範圍。
1

當他們說「不要」時,有幾條評論是非常不合格的。這太嚴厲了,但你必須明白什麼時候可以。

書寫using std::string永遠不會。在你自己的頭文件中寫入using ImplementationDetail::Foo,當頭文件聲明ImplementationDetail :: Foo可以正常時,如果使用聲明發生在你的名字空間中,則更是如此。例如。

namespace MyNS { 
    namespace ImplementationDetail { 
     int Foo; 
    } 
    using ImplementationDetail::Foo; 
}