为什么要包括“使用命名空间”?在 C++ 中将其写入头文件是一个坏主意吗?

发布于 2024-10-16 01:07:03 字数 311 浏览 2 评论 0原文

在阅读 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

温柔戏命师 2024-10-23 01:07:03

考虑这个程序:

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... 并将其放入头文件中,然后将其 #include 在 main() 之前。没有任何改变:你仍然有一个错误。因此,就像独立程序一样,其中包含 using 语句的头文件可能会给包含它们的其他代码带来麻烦,使它们的某些语句不明确。

但这可能是一个更大的痛苦,因为标头可以直接或间接地包含在任意大量的依赖代码中,并且......

  • 从标头中删除 using 语句,或者
  • 更改 的内容,或影响 std:: 的任何其他标头

...可能会破坏包括有问题的标头在内的代码。任何一个问题都可能导致相关代码无法编译,并且在尝试另一次编译之前甚至可能不会注意到问题。此外,因 using 语句而遭受痛苦的人可能没有文件系统/代码存储库权限、公司权限等来从标头中删除 using 语句,也无法修复其他问题。受影响的客户端代码。

也就是说,如果标头仅在类或函数内部具有“using”,则对该范围之外的代码没有影响,因此对 std:: 更改的潜在影响会大大减少。

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.

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.

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 affecting 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.

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.

伴随着你 2024-10-23 01:07:03

如果标头包含 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.

日记撕了你也走了 2024-10-23 01:07:03

复制《C++ Primer,第五版》中的以下段落:

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

Copy the following paragraph from "C++ Primer, fifth edition":

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.

染柒℉ 2024-10-23 01:07:03

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

假设您有一些非常常见的类名,例如 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; 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文