为什么要包括“使用命名空间”?在 C++ 中将其写入头文件是一个坏主意吗?
在阅读 Bruce Eckel 的《Thinking in C++》中有关命名空间的内容时,我遇到了以下说法:
但是你几乎永远不会看到 头文件中的 using 指令 (至少不超出范围)。这 原因是使用指令 消除对那个的保护 特定的命名空间以及效果 持续到当前结束 编译单位。如果你放置一个使用 指令(在范围之外) 头文件,这意味着丢失了 “命名空间保护”将发生在 任何包含此内容的文件 标头,通常意味着其他标头 文件。
您愿意用一些简单的例子帮助我理解上述陈述吗?
While reading from Bruce Eckel's "Thinking in C++" about namespaces, I encountered the following statement:
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.
Would you please like to help me to comprehend the above statement with some easy example?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
考虑这个程序:
如果你尝试编译它,你会看到错误:
这里的问题是,当
main()
指定string x;
时,编译器不确定是否需要用户定义的::string
或包含的std::string
。现在想象一下,您将程序的顶部部分...第 1 行到第 5 行 - 直到并包括
struct string
... 并将其放入头文件中,然后将其 #include 在main()
之前。没有任何改变:你仍然有一个错误。因此,就像独立程序一样,其中包含using
语句的头文件可能会给包含它们的其他代码带来麻烦,使它们的某些语句不明确。但这可能是一个更大的痛苦,因为标头可以直接或间接地包含在任意大量的依赖代码中,并且......
using
语句,或者
的内容,或影响std::
的任何其他标头...可能会破坏包括有问题的标头在内的代码。任何一个问题都可能导致相关代码无法编译,并且在尝试另一次编译之前甚至可能不会注意到问题。此外,因
using
语句而遭受痛苦的人可能没有文件系统/代码存储库权限、公司权限等来从标头中删除using
语句,也无法修复其他问题。受影响的客户端代码。也就是说,如果标头仅在类或函数内部具有“using”,则对该范围之外的代码没有影响,因此对 std:: 更改的潜在影响会大大减少。
Consider this program:
If you try to compile it, you'll see errors:
The problem here is that when
main()
specifiesstring x;
, the compiler's not sure whether the user-defined::string
or includedstd::string
is wanted.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
beforemain()
. Nothing changes: you still have an error. So, just as for standalone programs, header files withusing
statements in them can cause trouble for other code that includes them, making some of their statements ambiguous.It can be a bigger pain though, as headers can be included - directly or indirectly - by arbitrarily huge amounts of dependent code, and...
using
statement from the header, or<string>
, or any other header affectingstd::
...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 theusing
statement from the header, nor fix other affected client code.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.
如果标头包含
using namespace std
,则该命名空间中的所有内容都会添加到包含该标头的每个模块中的全局命名空间。这意味着您永远不能在任何这些模块的全局命名空间中声明函数或定义与全局命名空间中的 std 函数/类具有相同名称(以及函数的兼容参数)的函数或类。
If a header contains
using namespace std
, everything from that namespace is added the global namespace in every module that includes the header.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.复制《C++ Primer,第五版》中的以下段落:
Copy the following paragraph from "C++ Primer, fifth edition":
那么,使用命名空间有什么意义呢?这是为了避免名称冲突的风险。
假设您有一些非常常见的类名,例如 FooBar。如果您使用多个库,则存在库 A 中的 FooBar 与库 B 中的 FooBar 发生冲突的风险。为此,我们使用两个不同的命名空间 A 和 B,将 FooBar 从全局命名空间移动到 A::FooBar 和 B::FooBar (因此它们彼此分开)。
如果您随后将
using A;
和using B;
放入标头中,则会将 A::FooBar 和 B::FooBar 移动到 FooBar,从而恢复碰撞,首先消除使用名称空间的好处。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).
If you then put
using A;
andusing 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.