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

发布于 2024-11-04 13:27:24 字数 647 浏览 2 评论 0原文

在我们所有的 C++ 课程中,所有老师总是将 using namespace std; 放在 .h 文件中的 #include 之后。在我看来,这似乎很危险,因为通过在另一个程序中包含该标头,我会将名称空间导入到我的程序中,也许没有意识到、打算或想要它(标头包含可以非常深入地嵌套)。

所以我的问题是双重的:我是否正确地认为 using namespace 不应在头文件中使用,和/或是否有某种方法可以撤消它,例如:

//header.h
using namespace std {
.
.
.
}

还有一个同样的问题:应该头文件 #include 其对应的 .cpp 文件需要的所有头文件,仅包含那些头定义所需的头文件,并让 .cpp > 文件 #include 其余部分,或无并将其需要的所有内容声明为 extern
这个问题背后的原因与上面相同:我不希望在包含 .h 文件时出现意外。

另外,如果我是对的,这是一个常见的错误吗?我的意思是在现实世界的编程和“真实”的项目中。

谢谢。

In all our c++ courses, all the teachers always put using namespace std; right after the #includes 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).

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

Also, if I am right, is this a common mistake? I mean in real-world programming and in "real" projects out there.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(9

御守 2024-11-11 13:27:24

您绝对不应该在标头中使用 using namespace ,正如您所说的那样,它可能会意外地更改包含该标头的任何其他文件中的代码含义。无法撤消 using namespace 这是它如此危险的另一个原因。我通常只使用 grep 或类似的东西来确保 using namespace 不会在标头中被调用,而不是尝试任何更复杂的事情。静态代码检查器可能也会标记这一点。

标头应仅包含需要编译的标头。强制执行此操作的一个简单方法是始终将每个源文件自己的标头作为第一件事包含在任何其他标头之前。如果标头不是独立的,则源文件将无法编译。在某些情况下,例如引用库中的实现细节类,您可以使用前向声明而不是#include,因为您可以完全控制此类前向声明​​类的定义。

我不确定我是否会称其为常见,但它肯定偶尔会出现一次,通常是由不知道负面后果的新程序员编写的。通常,只需进行一些有关风险的教育就可以解决所有问题,因为解决起来相对简单。

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.

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.

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.

冬天旳寂寞 2024-11-11 13:27:24

Sutter 和 Alexandrescu 的 “C++ 编码标准:101 条规则、指南和最佳实践”中的第 59 条

59。不要在头文件中或 #include 之前编写命名空间 using。

命名空间 using 是为了您的方便,而不是为了您对他人造成伤害:切勿在之前编写 using 声明或 using 指令#include 指令。

推论:在头文件中,不要编写命名空间级 using 指令或 using 声明;相反,显式地对所有名称进行命名空间限定。

头文件是一个或多个源文件中的一个客体。包含 using 指令和声明的头文件也带来了它的吵闹伙伴。

using声明引入了一个伙伴。 using 指令引入命名空间中的所有伙伴。您的教师对 using namespace std; 的使用是一个 using 指令。

更严重的是,我们有命名空间来避免名称冲突。头文件旨在提供一个接口。大多数标头不知道现在或将来哪些代码可能包含它们。为了内部方便,在标头中添加 using 语句会将这些方便的名称强加给该标头的所有潜在客户端。这可能会导致名称冲突。这简直是​​粗鲁无礼。

Item 59 in Sutter and Alexandrescu's "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices":

59. Don’t write namespace usings in a header file or before an #include.

Namespace usings are for your convenience, not for you to inflict on others: Never write a using declaration or a using directive before an #include directive.

Corollary: In header files, don't write namespace-level using directives or using declarations; instead, explicitly namespace-qualify all names.

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.

A using declaration brings in one buddy. A using directive brings in all the buddies in the namespace. Your teachers' use of 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. 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.

两仪 2024-11-11 13:27:24

在标题中包含标题时需要小心。在大型项目中,它可能会创建一个非常混乱的依赖链,从而触发比实际需要更大/更长的重建。查看这篇文章其后续内容,详细了解良好物理结构在 C++ 项目中的重要性。

仅当绝对需要时(每当需要类的完整定义时)才应在标头内包含标头,并尽可能使用前向声明(当需要的类是指针或引用时)。

至于命名空间,我倾向于在头文件中使用显式命名空间范围,并且只在我的 cpp 文件中放置 using namespace

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.

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.

独行侠 2024-11-11 13:27:24

关于“是否有某种方法可以撤消 [a using 声明]?”

我认为指出 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

所以有效的是。通过限制 using 声明的范围,其效果仅在该范围内持续;当该范围结束时,它会被“撤消”。

using 声明在任何其他作用域之外的文件中声明时,它具有文件作用域并影响该文件中的所有内容。

对于头文件,如果 using 声明位于文件范围内,则这将扩展到包含该头文件的任何文件的范围。

With regards to "Is there some way to undo [a using declaration]?"

I think it is useful to point out that using declarations are affected by 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; it is 'undone' when that scope ends.

When the using declaration is declared in a file outside of any other scope it has file-scope and affects everything in that file.

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.

妄司 2024-11-11 13:27:24

查看戈达德太空飞行中心编码标准(针对 C 和 C++)。事实证明,这比以前要困难一些 - 请参阅 SO 问题的更新答案:

GSFC C++ 编码标准说:

§3.3.7 每个头文件应#include其需要编译的文件,而不是强迫用户#include所需的文件。 #includes 应仅限于标头所需的内容;其他#includes 应放置在源文件中。

第一个交叉引用问题现在包括 GSFC C 编码标准的引用及其基本原理,但实质内容最终是相同的。

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:

The GSFC C++ coding standard says:

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

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.

百思不得你姐 2024-11-11 13:27:24

您是对的,在标头中使用名称空间是危险的。
我不知道如何撤消它。
检测它很容易,但只需在头文件中搜索 using namespace 即可。
由于最后一个原因,它在实际项目中并不常见。如果有人做了类似的事情,更有经验的同事很快就会抱怨。

在实际项目中,人们试图最大限度地减少包含文件的数量,因为包含的文件越少,编译速度就越快。这节省了每个人的时间。但是,如果头文件假定应在其之前包含某些内容,则它本身应包含该内容。否则它会使标头不独立。

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.

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.

极度宠爱 2024-11-11 13:27:24

我相信,如果您在如下所示的嵌套命名空间中编写声明,则可以安全地在 C++ 标头中使用“using”:

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;

这应该仅包含在“DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED”中声明的内容,而不包含使用的命名空间。我已经在 mingw64 编译器上测试过了。

I believe you can use 'using' in C++ headers safely if you write your declarations in a nested namespace like this:

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.

一向肩并 2024-11-11 13:27:24

你是对的。并且任何文件都应该只包含该文件所需的标头。至于“在现实世界的项目中做错事很常见吗?” - 哦是的!

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!

遮云壑 2024-11-11 13:27:24

就像编程中的所有事情一样,实用主义应该战胜教条主义,IMO。

只要您在项目范围内做出决定(“我们的项目广泛使用 STL,并且我们不想在所有内容前添加 std::。”),我就看不出它有什么问题。毕竟,您面临的唯一风险是名称冲突,而且随着 STL 的普遍存在,这不太可能成为问题。

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

Like all things in programming, pragmatism should win over dogmatism, 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.

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.

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