为什么在 C++ 中将“使用命名空间”包含到头文件中是个坏主意?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4872373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is including "using namespace" into a header file a bad idea in C++?
提问by user388338
While reading from Bruce Eckel's "Thinking in C++" about namespaces, I encountered the following statement:
在阅读 Bruce Eckel 关于命名空间的“Thinking in C++”时,我遇到了以下语句:
However you'll virtually never see a using directive in a header file (at least not outside of scope). The reason is that using directive eliminate the protection of that particular namespace, and the effect last until the end of current compilation unit. If you put a using directive (outside of a scope) in a header file, it means that this loss of "namespace protection" will occur within any file that include this header, which often mean other header files.
但是,您几乎永远不会在头文件中看到 using 指令(至少不在范围之外)。原因是 using 指令消除了对该特定命名空间的保护,并且效果持续到当前编译单元结束。如果将 using 指令(在作用域之外)放在头文件中,则意味着在包含此头文件的任何文件中都会发生这种“命名空间保护”的丢失,这通常意味着其他头文件。
Would you please like to help me to comprehend the above statement with some easy example?
你愿意用一些简单的例子帮助我理解上面的陈述吗?
回答by Tony Delroy
Consider this program:
考虑这个程序:
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 }
If you try to compile it, you'll see errors:
如果你尝试编译它,你会看到错误:
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"
The problem here is that when main()
specifies string x;
, the compiler's not sure whether the user-defined ::string
or included std::string
is wanted.
这里的问题是,当main()
指定时string x;
,编译器不确定是否需要用户定义::string
或包含std::string
。
Now imagine you take the top part of the program... lines 1 through 5 - up to and including the struct string
... and put it into a header file which you then #include
before main()
. Nothing changes: you still have an error. So, just as for standalone programs, header files with using
statements in them can cause trouble for other code that includes them, making some of their statements ambiguous.
现在假设您将程序的顶部...第 1 行到第 5 行 - 直到并包括struct string
... 并将其放入头文件中,然后#include
在main()
. 没有任何变化:您仍然有错误。因此,就像对于独立程序一样,其中包含using
语句的头文件可能会给包含它们的其他代码带来麻烦,从而使它们的某些语句变得模棱两可。
It can be a bigger pain though, as headers can be included - directly or indirectly - by arbitrarily huge amounts of dependent code, and...
但是,这可能会带来更大的痛苦,因为可以通过任意大量的依赖代码直接或间接地包含标头,并且...
- removing the
using
statement from the header, or - a change to the contents of
<string>
, or any other header affectingstd::
using
从标题中删除语句,或- 的内容更改
<string>
,或任何其他影响std::
...might break code including the problematic header. Either problem may render dependent code uncompilable, and issues may not even be noticed until another compilation is attempted. Further, the person suffering due to the using
statement may not have filesystem/code-repository permissions, corporate authority etc. to remove the using
statement from the header, nor fix other affected client code.
...可能会破坏代码,包括有问题的标题。任何一个问题都可能导致相关代码无法编译,并且在尝试另一次编译之前甚至可能不会注意到问题。此外,由于该using
语句而遭受痛苦的人可能没有文件系统/代码存储库权限、公司权限等,无法using
从标题中删除该语句,也没有修复其他受影响的客户端代码。
That said, if a header only has "using" inside a class or function, then there's no affect on code beyond that scope, so the potential impact of changes to std:: is dramatically reduced.
也就是说,如果头文件只在类或函数内部“使用”,那么对超出该范围的代码没有影响,因此对 std:: 更改的潜在影响显着减少。
回答by Fred Foo
If a header contains using namespace std
, everything from that namespace is added the global namespace in every module that includes the header.
如果标头包含using namespace std
,则该命名空间中的所有内容都将添加到包含标头的每个模块中的全局命名空间。
This means you can never declare a function or define a class with the same name (and compatible parameters for a function) as an std
function/class in the global namespace in any of those modules.
这意味着您永远不能std
在任何这些模块的全局命名空间中声明一个函数或定义一个与函数/类具有相同名称(和函数的兼容参数)的类。
回答by Shen
Copy the following paragraph from "C++ Primer, fifth edition":
从“C++ 入门,第五版”中复制以下段落:
Code inside headers ordinarily should not use
using
declarations. The reason is that the contents of a header are copied into the including program's text. If a header has a using declaration, then every program that includes that header gets that same using declaration. As a result, a program that didn't intent to use the specified library name might encounter unexpected name conflicts.
标头内的代码通常不应使用
using
声明。原因是标题的内容被复制到包含程序的文本中。如果头文件有 using 声明,则包含该头文件的每个程序都会获得相同的 using 声明。因此,无意使用指定库名称的程序可能会遇到意外的名称冲突。
回答by Johan Kotlinski
Well, what is the point of using namespaces. It is to avoid the risk of name collisions.
那么,使用命名空间有什么意义呢?这是为了避免名称冲突的风险。
Let's say that you have some pretty common class name, for example FooBar. If you use several libraries, there is the risk that FooBar in library A collides with FooBar in library B. For that we use two different namespaces A and B, to move the FooBars from global namespace to A::FooBar and B::FooBar (so they are kept separate from each other).
假设您有一些非常常见的类名,例如 FooBar。如果您使用多个库,则存在库 A 中的 FooBar 与库 B 中的 FooBar 冲突的风险。为此,我们使用两个不同的命名空间 A 和 B,将 FooBar 从全局命名空间移动到 A::FooBar 和 B::FooBar (因此它们彼此分开)。
If you then put using A;
and using B;
in headers, this will then move A::FooBar and B::FooBar to just FooBar, bringing back the collision, removing the gain from using namespaces in the first place.
如果您随后放入using A;
并using B;
放入标头,这会将 A::FooBar 和 B::FooBar 移动到仅 FooBar,从而恢复碰撞,首先消除使用命名空间的好处。