C++ 头文件中的“使用命名空间”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5849457/
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
"using namespace" in c++ headers
提问by Baruch
In all our c++ courses, all the teachers always put using namespace std;
right after the #include
s in their .h
files. This seems to me to be dangerous since then by including that header in another program I will get the namespace imported into my program, maybe without realizing, intending or wanting it (header inclusion can be very deeply nested).
在我们所有的 c++ 课程中,所有的老师总是在他们的文件中using namespace std;
紧跟在#include
s之后.h
。在我看来,这似乎很危险,因为通过在另一个程序中包含该头文件,我会将命名空间导入到我的程序中,可能没有意识到、有意或想要它(头文件包含可以非常深入地嵌套)。
So my question is double: Am I right that using namespace
should not be used in header files, and/or is there some way to undo it, something like:
所以我的问题是双重的:我using namespace
不应该在头文件中使用它,和/或有什么方法可以撤消它,例如:
//header.h
using namespace std {
.
.
.
}
One more question along the same lines: Should a header file #include
all the headers that it's corresponding .cpp
file needs, only those that are needed for the header definitions and let the .cpp
file #include
the rest, or none and declare everything it needs as extern
?
The reasoning behind the question is the same as above: I don't want surprises when including .h
files.
还有一个类似的问题:头文件是否应该包含#include
它对应的.cpp
文件需要的所有头文件,只有那些头文件定义需要的头.cpp
文件并让文件#include
剩下,或者没有并声明它需要的所有内容extern
?
问题背后的原因与上述相同:我不希望在包含.h
文件时出现意外。
Also, if I am right, is this a common mistake? I mean in real-world programming and in "real" projects out there.
另外,如果我是对的,这是一个常见的错误吗?我的意思是在现实世界的编程和那里的“真实”项目中。
Thank you.
谢谢你。
采纳答案by Mark B
You should definitely NOT use using namespace
in headers for precisely the reason you say, that it can unexpectedly change the meaning of code in any other files that include that header. There's no way to undo a using namespace
which is another reason it's so dangerous. I typically just use grep
or the like to make sure that using namespace
isn't being called out in headers rather than trying anything more complicated. Probably static code checkers flag this too.
您绝对不应该using namespace
因为您所说的原因在标题中使用它,它可能会意外地更改包含该标题的任何其他文件中的代码含义。无法撤消 ausing namespace
这是它如此危险的另一个原因。我通常只是使用grep
或类似的方法来确保using namespace
不会在标题中被调用,而不是尝试任何更复杂的东西。可能静态代码检查器也标记了这一点。
The header should include just the headers that it needs to compile. An easy way to enforce this is to always include each source file's own header as the first thing, before any other headers. Then the source file will fail to compile if the header isn't self-contained. In some cases, for example referring to implementation-detail classes within a library, you can use forward declarations instead of #include
because you have full control over the definition of such forward declared class.
头文件应该只包含它需要编译的头文件。强制执行此操作的一种简单方法是始终将每个源文件自己的标头作为第一件事,在任何其他标头之前。如果标头不是自包含的,那么源文件将无法编译。在某些情况下,例如引用库中的实现细节类,您可以使用前向声明而不是#include
因为您可以完全控制此类前向声明类的定义。
I'm not sure I would call it common, but it definitely shows up once in a while, usually written by new programmers that aren't aware of the negative consequences. Typically just a little education about the risks takes care of any issues since it's relatively simple to fix.
我不确定我会称它为普通,但它肯定会偶尔出现,通常是由不知道负面后果的新程序员编写的。通常只需对风险进行一点教育即可解决任何问题,因为修复起来相对简单。
回答by Andy Thomas
Item 59 in Sutter and Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices":
Sutter 和 Alexandrescu 的“C++ 编码标准:101 条规则、指南和最佳实践”中的第 59条:
59. Don't write namespace usings in a header file or before an #include.
Namespace
using
s are for your convenience, not for you to inflict on others: Never write ausing
declaration or ausing
directive before an#include
directive.Corollary: In header files, don't write namespace-level
using
directives orusing
declarations; instead, explicitly namespace-qualify all names.
59. 不要在头文件中或 #include 之前编写命名空间 using。
命名空间
using
是为了您的方便,而不是让您强加于他人:永远不要using
在using
指令之前编写声明或#include
指令。推论:在头文件中,不要写命名空间级别的
using
指令或using
声明;相反,明确命名空间限定所有名称。
A header file is a guest in one or more source files. A header file that includes using
directives and declarations brings its rowdy buddies over too.
头文件是一个或多个源文件中的客体。一个包含using
指令和声明的头文件也带来了它吵闹的伙伴。
A using
declarationbrings in one buddy. A using
directivebrings in all the buddies in the namespace. Your teachers' use of using namespace std;
is a using directive.
一个using
声明带来了一个伙伴。一个using
指令会引入命名空间中的所有伙伴。你的老师的 use ofusing namespace std;
是 using 指令。
More seriously, we have namespaces to avoid name clash. A header file is intended to provide an interface. Most headers are agnostic of what code may include them, now or in the future. Adding using
statements for internal convenience within the header foists those convenient names on all the potential clients of that header. That can lead to name clash. And it's just plain rude.
更严重的是,我们有命名空间来避免名称冲突。头文件旨在提供一个接口。大多数标头不知道现在或将来可能包含哪些代码。using
在头文件中为内部方便而添加的语句将这些方便的名称强加在该头文件的所有潜在客户上。这可能会导致名称冲突。这只是粗鲁的。
回答by Mike O'Connor
You need to be careful when including headers inside of headers. In large projects, it can create a very tangled dependency chain that triggers larger/longer rebuilds than were actually necessary. Check out this articleand its follow-upto learn more about the importance of good physical structure in C++ projects.
在标题中包含标题时需要小心。在大型项目中,它可以创建一个非常复杂的依赖链,触发比实际需要更大/更长的重建。查看这篇文章及其后续文章,以了解有关良好物理结构在 C++ 项目中的重要性的更多信息。
You should only include headers inside a header when absolutely needed (whenever the full definition of a class is needed), and use forward declaration wherever you can (when the class is required is a pointer or a reference).
您应该只在绝对需要时(当需要类的完整定义时)在头文件中包含头文件,并尽可能使用前向声明(当需要的类是指针或引用时)。
As for namespaces, I tend to use the explicit namespace scoping in my header files, and only put a using namespace
in my cpp files.
至于命名空间,我倾向于在我的头文件中使用显式命名空间范围,并且只using namespace
在我的 cpp 文件中放置 a 。
回答by Jonathan Leffler
Check out the Goddard Space Flight Center coding standards (for C and C++). That turns out to be a bit harder than it used to be - see the updated answers to the SO questions:
查看 Goddard Space Flight Center 编码标准(适用于 C 和 C++)。事实证明,这比以前更难了 - 请参阅 SO 问题的更新答案:
The GSFC C++ coding standard says:
GSFC C++ 编码标准说:
§3.3.7 Each header file shall
#include
the files it needs to compile, rather than forcing users to#include
the needed files.#includes
shall be limited to what the header needs; other#includes
should be placed in the source file.
§3.3.7 每个头文件
#include
都是它需要编译的文件,而不是强迫用户编译#include
需要的文件。#includes
应限于标题需要的内容;其他#includes
应该放在源文件中。
The first of the cross-referenced questions now includes a quote from the GSFC C coding standard, and the rationale, but the substance ends up being the same.
交叉引用的第一个问题现在包括引用 GSFC C 编码标准和基本原理,但内容最终是相同的。
回答by ?? Tiib
You are right that using namespace
in header is dangerous.
I do not know a way how to undo it.
It is easy to detect it however just search for using namespace
in header files.
For that last reason it is uncommon in real projects. More experienced coworkers will soon complain if someone does something like it.
你是对的,using namespace
标题是危险的。我不知道如何撤消它。很容易检测到它,但是只需using namespace
在头文件中搜索即可。由于最后一个原因,它在实际项目中并不常见。如果有人做了类似的事情,更有经验的同事很快就会抱怨。
In real projects people try to minimize the amount of included files, because the less you include the quicker it compiles. That saves time of everybody. However if the header file assumes that something should be included before it then it should include it itself. Otherwise it makes headers not self-contained.
在实际项目中,人们会尽量减少包含文件的数量,因为包含的文件越少,编译速度就越快。这样可以节省大家的时间。但是,如果头文件假设应该在它之前包含某些内容,那么它应该包含它本身。否则它会使标题不独立。
回答by ?? Tiib
You are right. And any file should only include the headers needed by that file. As for "is doing things wrong common in real world projects?" - oh, yes!
你是对的。任何文件都应该只包含该文件所需的头文件。至于“在现实世界的项目中做错事很常见吗?” - 哦是的!
回答by ijprest
Like all things in programming, pragmatism should win over dogmatism, IMO.
就像编程中的所有事情一样,实用主义应该战胜教条主义,IMO。
So long as you make the decision project-wide ("Our project uses STL extensively, and we don't want to have to prepend everything with std::."), I don't see the problem with it. The only thing you're risking is name collisions, after all, and with the ubiquity of STL it's unlikely to be a problem.
只要您在整个项目范围内做出决定(“我们的项目广泛使用 STL,我们不想在所有内容前加上 std::.”),我就看不出它有什么问题。毕竟,您唯一要冒的风险就是名称冲突,而且随着 STL 的普遍性,这不太可能成为问题。
On the other hand, if it was a decision by one developer in a single (non-private) header-file, I can see how it would generate confusion among the team and should be avoided.
另一方面,如果这是一个开发人员在单个(非私有)头文件中的决定,我可以看到它会如何在团队中产生混淆并且应该避免。
回答by YoungJohn
With regards to "Is there some way to undo [a using
declaration]?"
关于“有没有办法撤销[using
声明]?”
I think it is useful to point out that using
declarations are affected by scope.
我认为指出using
声明受范围影响是有用的。
#include <vector>
{ // begin a new scope with {
using namespace std;
vector myVector; // std::vector is used
} // end the scope with }
vector myOtherVector; // error vector undefined
std::vector mySTDVector // no error std::vector is fully qualified
So effectively yes. By limiting the scope of the using
declaration its effect only lasts within that scope; it is 'undone' when that scope ends.
如此有效,是的。通过限制using
声明的范围,其效力仅在该范围内持续;当该范围结束时,它被“撤销”。
When the using
declaration is declared in a file outside of any other scope it has file-scope and affects everything in that file.
当using
声明在任何其他范围之外的文件中声明时,它具有文件范围并影响该文件中的所有内容。
In the case of a header file, if the using
declaration is at file-scope this will extend to the scope of any file the header is included in.
在头文件的情况下,如果using
声明在文件范围内,这将扩展到包含头文件的任何文件的范围。
回答by AnArrayOfFunctions
I believe you can use 'using' in C++ headers safely if you write your declarations in a nested namespace like this:
我相信如果您在嵌套命名空间中编写声明,则可以安全地在 C++ 标头中使用“使用”,如下所示:
namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED
{
/*using statements*/
namespace DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED
{
/*declarations*/
}
}
using namespace DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED::DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED;
This should include only the things declared in 'DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED' without the namespaces used. I have tested it on mingw64 compiler.
这应该只包括在“DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED”中声明的东西,而没有使用的命名空间。我已经在 mingw64 编译器上对其进行了测试。