&引用;使用名称空间";在c++;标题 在我们所有的C++课程中,所有教师都使用名称空间STD来设置;代码>在#之后,将包含在其.h文件中。在我看来,这似乎是危险的,因为通过在另一个程序中包含该头,我将把名称空间导入到我的程序中,可能没有意识到、打算或想要它(头包含可以是非常深的嵌套)

&引用;使用名称空间";在c++;标题 在我们所有的C++课程中,所有教师都使用名称空间STD来设置;代码>在#之后,将包含在其.h文件中。在我看来,这似乎是危险的,因为通过在另一个程序中包含该头,我将把名称空间导入到我的程序中,可能没有意识到、打算或想要它(头包含可以是非常深的嵌套),c++,namespaces,header-files,C++,Namespaces,Header Files,所以我的问题是双重的:我是否正确地认为头文件中不应该使用使用名称空间,和/或是否有某种方法可以撤销它,比如: //header.h using namespace std { . . . } 同样,还有一个问题:头文件#应该包含它对应的.cpp文件需要的所有头文件,只包含头定义所需的头文件,并让.cpp文件包含其余的头文件,还是不包含,并将它需要的所有内容声明为extern? 这个问题背后的原因与上面相同:我不希望在包含.h文件时出现意外 还有,如果我是对的,这是一个常见的错误吗?我的意思是在

所以我的问题是双重的:我是否正确地认为头文件中不应该使用
使用名称空间
,和/或是否有某种方法可以撤销它,比如:

//header.h
using namespace std {
.
.
.
}
同样,还有一个问题:头文件
#应该包含它对应的
.cpp
文件需要的所有头文件,只包含头定义所需的头文件,并让
.cpp
文件
包含其余的头文件,还是不包含,并将它需要的所有内容声明为
extern

这个问题背后的原因与上面相同:我不希望在包含
.h
文件时出现意外

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


谢谢。你说得对。任何文件都应该只包含该文件所需的标题。至于“做错事在现实世界的项目中是常见的吗?”-哦,是的

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


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

在标题中包含标题时需要小心。在大型项目中,它可以创建一个非常复杂的依赖链,触发比实际需要更大/更长的重建。检查并了解C++项目中良好物理结构的重要性。

只有在绝对需要时(无论何时需要类的完整定义),才应该在头中包含头,并尽可能使用前向声明(当需要类是指针或引用时)


至于名称空间,我倾向于在头文件中使用显式名称空间作用域,并且只在我的cpp文件中使用
使用名称空间

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

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


我不确定我会称之为“普通”,但它肯定会偶尔出现,通常是由没有意识到负面后果的新程序员编写的。通常,只要对风险进行一点教育,就可以解决任何问题,因为修复起来相对简单。

与编程中的所有事情一样,我认为实用主义应该战胜教条主义

只要您在整个项目范围内做出决策(“我们的项目广泛使用STL,我们不想用std::。”预先准备所有内容”),我就看不出它有什么问题。毕竟,你唯一要冒的风险就是名称冲突,而且随着STL的普及,这不太可能成为一个问题


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

Sutter和Alexandrescu的第59项:

59。不要在头文件中或在包含之前写入命名空间。

命名空间
使用
s是为了您的方便,而不是为了您对他人施加影响:切勿在
#include
指令之前编写
使用
声明或
使用
指令

推论:在头文件中,不要使用
指令或使用
声明编写命名空间级别的
;而是显式地限定所有名称

头文件是一个或多个源文件中的来宾文件。一个包含
指令和声明的头文件也会带来它的好朋友

使用
声明的
会带来一个好友。使用
指令的
会引入名称空间中的所有伙伴。你的老师使用
名称空间std
是一个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;
#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