2011-02-02 62 views
24

虽然布鲁斯Eckel的“思考在C++”关于命名空间的阅读,我遇到了以下声明:为什么在C++中包含“使用名称空间”到头文件中是一个坏主意?

但是你几乎从来没有在头文件 使用范围指令(至少不是外面看到 )。原因是 的原因是使用指令 消除了该特定命名空间的保护,并且效果 直到当前 编译单元结束。如果你在一个 头文件把使用 指令(一个范围之外),这意味着 “命名空间保护”的这方面的损失将在 发生的包括该 头,这往往意味着其他头 文件的任何文件。

您是否愿意通过一些简单的例子来帮助我理解上述说明?

+3

叶氏,在这里你去:http://stackoverflow.com/questions/2152925/can-i-undo-the-effect-of-using-namespace-in-c – sharptooth 2011-02-02 08:53:07

+4

@sharptooth:“让我的StackOverflow那为你“弹入我的头:) – Mehrdad 2011-02-02 08:59:04

+0

@Mehrdad:大声笑,我希望我们永远不会到那个阶段。 – sharptooth 2011-02-02 09:09:41

回答

25

考虑此程序:

line# 
    1 #include <string>                
    2                     
    3 using namespace std;                
    4                     
    5 struct string { const char* p; }; // Beware: another string! 
    6                     
    7 int main()                  
    8 {                    
    9  string x; // Error: ambiguous - which string is wanted? 
    10 } 

如果你尝试编译它,你会看到错误:

g++  using.cc -o using 
using.cc: In function `int main()': 
using.cc:9: error: use of `string' is ambiguous 
using.cc:5: error: first declared as `struct string' here 
/usr/lib/gcc/i386-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stringfwd.h:60: error: 
    also declared as `typedef struct std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::string' here 
using.cc:9: error: `string' was not declared in this scope 
using.cc:9: error: expected `;' before "x" 

这里的问题是,当main()指定string x;,编译器不能确定是否用户定义的::string或包括std::string是需要的。

现在想象一下,您将程序的顶部......第1行至第5行 - 直至并包括struct string ......并将其放入一个头文件中,然后您在main()之前#include。没有任何变化:您仍然有错误。因此,就像独立程序一样,其中包含using语句的头文件可能会导致包含它们的其他代码出现问题,从而导致它们的某些语句不明确。

尽管它可以是一个更大的痛苦,因为标题可以被直接或间接地包含在任意大量的依赖代码中,并且...

  • 从头部取出using声明,或
  • 更改的<string>内容,或影响std::

任何其他头......可能会破坏代码,包括有问题的头。任何一个问题都可能导致相关代码无法编译,并且直到尝试执行另一个编译时才会注意到问题。此外,由于using声明造成的人可能没有文件系统/代码存储库权限,公司权限等从头中删除using语句,也无法修复其他受影响的客户端代码。也就是说,如果头只在类或函数中有“使用”,那么超出该范围的代码不会受到影响,所以对std ::的更改的潜在影响大大降低。

15

如果标题包含using namespace std,则该名称空间中的所有内容都将添加到包含标题的每个模块中的全局名称空间中。

这意味着您不能在任何这些模块的全局名称空间中声明函数或定义具有相同名称(以及函数的兼容参数)的类作为std函数/类。

4

那么,使用名称空间有什么意义。这是为了避免名称冲突的风险。

比方说,你有一些很常见的类名,例如FooBar。如果您使用多个库,则库A中的FooBar与库B中的FooBar发生冲突。为此,我们使用两个不同的名称空间A和B将FooBars从全局名称空间移动到A :: FooBar和B :: FooBar (所以他们保持彼此分开)。

如果您接着将using A;using B;放在标题中,则会将A :: FooBar和B :: FooBar移动到FooBar,从而使冲突恢复正常,从首先使用名称空间中删除增益。

4

复制从“C++入门,第五版”下面的段落:

内标题代码通常不应使用using声明。 原因是标题的内容被复制到包含 程序的文本中。如果一个头文件有一个using声明,那么包含该头文件的每个 程序使用声明获得相同的结果。由于 的结果,不打算使用指定的库名称的程序可能会遇到意外的名称冲突。

相关问题