简体   繁体   English

c++ 标头中的“使用命名空间”

[英]“using namespace” in c++ headers

In all our c++ courses, all the teachers always put using namespace std;在我们所有的 c++ 课程中,所有的老师总是把using namespace std; right after the #include s in their .h files.就在他们的.h文件中的#include之后。 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).从那时起,在我看来,通过将 header 包含在另一个程序中,这在我看来是危险的,我将把命名空间导入我的程序中,可能没有意识到、有意或想要它(标题包含可以非常深入地嵌套)。

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:所以我的问题是双重的:我是否正确不应在 header 文件中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 ? 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它需要作为extern
The reasoning behind the question is the same as above: I don't want surprises when including .h files.问题背后的原因与上述相同:我不想在包含.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.谢谢你。

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.由于您所说的原因,您绝对不应该在标头中使用using namespace ,因为它可能会意外地更改包含该 header 的任何其他文件中代码的含义。 There's no way to undo a using namespace which is another reason it's so dangerous.没有办法撤消using namespace ,这是它如此危险的另一个原因。 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.我通常只使用grep等来确保不会在标头中调用using namespace而不是尝试更复杂的操作。 Probably static code checkers flag this too.可能 static 代码检查器也会标记这一点。

The header should include just the headers that it needs to compile. header 应该只包含它需要编译的头文件。 An easy way to enforce this is to always include each source file's own header as the first thing, before any other headers.执行此操作的一种简单方法是始终将每个源文件自己的 header 作为第一件事包含在任何其他标头之前。 Then the source file will fail to compile if the header isn't self-contained.如果 header 不是独立的,则源文件将无法编译。 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 ,因为您可以完全控制此类前向声明的 class 的定义。

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.通常,只需对风险进行一点教育就可以解决任何问题,因为它相对容易修复。

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. 59. 不要在 header 文件中或 #include 之前写入命名空间 usings。

Namespace using s are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.命名空间using是为了您的方便,而不是让您强加于他人:切勿在#include指令之前编写using声明或using指令。

Corollary: In header files, don't write namespace-level using directives or using declarations;推论:在 header 文件中,不要编写命名空间级别的using指令或using声明; instead, explicitly namespace-qualify all names.相反,明确命名空间限定所有名称。

A header file is a guest in one or more source files. header 文件是一个或多个源文件中的来宾。 A header file that includes using directives and declarations brings its rowdy buddies over too.包含using指令和声明的 header 文件也将其吵闹的伙伴带到了这里。

A using declaration brings in one buddy. using声明带来了一个伙伴。 A using directive brings in all the buddies in the namespace. using指令会引入命名空间中的所有伙伴。 Your teachers' use of using namespace std;您的老师对using namespace std; is a using directive.是一个使用指令。

More seriously, we have namespaces to avoid name clash.更严重的是,我们有命名空间来避免名称冲突。 A header file is intended to provide an interface. header 文件旨在提供接口。 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.为了内部方便,在 header 中添加using语句会将这些方便的名称强加给 header 的所有潜在客户。 That can lead to name clash.这可能导致名称冲突。 And it's just plain rude.这很粗鲁。

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 article and its follow-up to 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).您应该仅在绝对需要时(只要需要 class 的完整定义时)在 header 中包含标头,并尽可能使用前向声明(当需要 class 时是指针或引用时)。

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.至于命名空间,我倾向于在我的 header 文件中使用显式命名空间范围,并且只在我的 cpp 文件中放置一个using namespace

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声明受 scope 影响是有用的。

#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;通过限制using声明的 scope,其效果仅在 scope 内持续; it is 'undone' when that scope ends.当 scope 结束时,它被“撤消”。

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声明在任何其他 scope 之外的文件中声明时,它具有文件范围并影响该文件中的所有内容。

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.对于 header 文件,如果using声明在文件范围内,这将扩展到包含 header 的任何文件的 scope。

Check out the Goddard Space Flight Center coding standards (for C and C++).查看戈达德太空飞行中心编码标准(C 和 C++)。 That turns out to be a bit harder than it used to be - see the updated answers to the SO questions:事实证明这比以前更难了 - 请参阅 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. §3.3.7 每个 header 文件都应#include它需要编译的文件,而不是强制用户#include需要的文件。 #includes shall be limited to what the header needs; #includes应限于 header 需要的内容; other #includes should be placed in the source file.其他#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 编码标准的引用,以及基本原理,但内容最终是相同的。

You are right that using namespace in header is dangerous.你是对的,在 header 中using namespace是危险的。 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.很容易检测到它,但是只需在 header 文件中搜索using namespace For that last reason it is uncommon in real projects.由于最后一个原因,它在实际项目中并不常见。 More experienced coworkers will soon complain if someone does something like it.如果有人做了类似的事情,更有经验的同事很快就会抱怨。

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.但是,如果 header 文件假定应该在它之前包含某些内容,那么它应该包含它本身。 Otherwise it makes headers not self-contained.否则,它会使标头不自包含。

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! - 哦是的!

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.只要您在整个项目范围内做出决定(“我们的项目广泛使用 STL,我们不想在所有内容前面都加上 std::.”),我看不出它有什么问题。 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 的普遍存在,这不太可能成为问题。

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.另一方面,如果这是一个开发人员在单个(非私有)头文件中的决定,我可以看到它会如何在团队中产生混乱,应该避免。

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.这应该只包括在 'DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED' 中声明的东西,而不包括使用的命名空间。 I have tested it on mingw64 compiler.我已经在 mingw64 编译器上对其进行了测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM