提问人:Baruch 提问时间:5/1/2011 更新时间:12/11/2019 访问量:113592
C++ 标头中的“using namespace” [duplicate]
"using namespace" in c++ headers [duplicate]
问:
在我们所有的 c++ 课程中,所有老师总是在他们的文件中将 s 放在后面。在我看来,这似乎是危险的,因为从那时起,通过将该标头包含在另一个程序中,我将把命名空间导入到我的程序中,也许没有意识到、打算或想要它(标头包含可以嵌套得非常深)。using namespace std;
#include
.h
所以我的问题是双重的:我是否正确,不应该在头文件中使用,和/或是否有某种方法可以撤消它,例如:using namespace
//header.h
using namespace std {
.
.
.
}
还有一个类似的问题:头文件应该归档它对应文件需要的所有头文件,只归档头定义所需的头文件,让文件处理其余部分,或者什么都不归档,并声明它需要的所有内容?
这个问题背后的原因与上面相同:我不希望在包含文件时出现意外。#include
.cpp
.cpp
#include
extern
.h
另外,如果我是对的,这是一个常见的错误吗?我的意思是在现实世界的编程和“真实”项目中。
谢谢。
答:
你是对的。任何文件都应仅包含该文件所需的标头。至于“在现实世界的项目中做错事很常见吗?”——哦,是的!
你是对的,在标题中是危险的。
我不知道如何撤消它。
它很容易检测到,但只需在头文件中搜索即可。
由于最后一个原因,这在实际项目中并不常见。如果有人做类似的事情,更有经验的同事很快就会抱怨。using namespace
using namespace
在实际项目中,人们会尽量减少包含的文件数量,因为包含的文件越少,编译速度就越快。这样可以节省每个人的时间。但是,如果头文件假定应该在它之前包含某些内容,那么它应该包含它本身。否则,它会使标头不是独立的。
在标头内包含标头时需要小心。在大型项目中,它可能会创建一个非常纠结的依赖链,触发比实际需要的更大/更长的重建。查看本文及其后续内容,详细了解良好物理结构在 C++ 项目中的重要性。
只有在绝对需要时(每当需要类的完整定义时),才应在标头中包含标头,并尽可能使用正向声明(当需要类时是指针或引用)。
至于命名空间,我倾向于在我的头文件中使用显式命名空间范围,并且只在我的 cpp 文件中放置一个。using namespace
评论
template
您绝对不应该在标头中使用,因为您所说的正是因为它可以意外地更改包含该标头的任何其他文件中代码的含义。没有办法撤消,这是它如此危险的另一个原因。我通常只是使用或类似的东西来确保它不会在标头中被调用,而不是尝试任何更复杂的东西。可能静态代码检查器也会标记这一点。using namespace
using namespace
grep
using namespace
标头应仅包含需要编译的标头。强制执行此操作的一种简单方法是始终将每个源文件自己的标头作为第一件事,而不是任何其他标头。然后,如果标头不是独立的,则源文件将无法编译。在某些情况下,例如,引用库中的实现详细信息类,可以使用正向声明,而不是因为您可以完全控制此类正向声明类的定义。#include
我不确定我是否会称它为常见,但它肯定会偶尔出现,通常是由没有意识到负面后果的新程序员编写的。通常,只需对风险进行一些教育即可解决任何问题,因为它相对容易解决。
评论
using
.cpp
3rdPartyLib::BigClassName<3rdPartyLib::AnotherBigName,3rdPartyLib::AnotherBigName>::Iterator
template
typedefs
using
.cpp
#include
using
{ /* using statement in between brackets */ }
就像编程中的所有事情一样,实用主义应该战胜教条主义,IMO。
只要你在项目范围内做出决定(“我们的项目广泛使用 STL,我们不想用 std::.”来预置所有内容“),我就看不出它有什么问题。毕竟,你唯一要冒的风险就是名称冲突,而且随着STL的无处不在,这不太可能成为问题。
另一方面,如果这是一个开发人员在单个(非私有)头文件中的决定,我可以看到它会在团队中产生混乱,应该避免。
Sutter 和 Alexandrescu 的“C++ 编码标准:101 条规则、指南和最佳实践”中的第 59 项:
59. 不要在头文件中或 #include 之前编写命名空间 usings。
命名空间是为了方便你,而不是为了你强加给别人:永远不要在指令之前写声明或指令。
using
using
using
#include
推论:在头文件中,不要编写命名空间级别的指令或声明;相反,显式命名空间限定所有名称。
using
using
头文件是一个或多个源文件中的来宾。包含指令和声明的头文件也会吸引吵闹的伙伴。using
一份宣言带来了一个伙伴。指令引入命名空间中的所有好友。教师的 use of 是 using 指令。using
using
using namespace std;
更严重的是,我们有命名空间来避免名称冲突。头文件旨在提供接口。大多数标头都不知道现在或将来可能包含哪些代码。为了内部方便,在标头中添加语句会将这些方便的名称强加给该标头的所有潜在客户。这可能会导致名称冲突。这简直是粗鲁的。using
查看戈达德太空飞行中心编码标准(适用于 C 和 C++)。事实证明,这比以前要难一些 - 请参阅 SO 问题的更新答案:
GSFC C++编码标准说:
§3.3.7 每个头文件都应包含它需要编译的文件,而不是强迫用户使用所需的文件。 应限于标头需要的内容;其他应放在源文件中。
#include
#include
#includes
#includes
第一个交叉引用的问题现在包括对 GSFC C 编码标准的引用和基本原理,但实质最终是相同的。
我相信如果你在嵌套命名空间中编写声明,你可以安全地在 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;
这应该只包括在“DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED”中声明的内容,而不使用命名空间。我已经在 mingw64 编译器上对其进行了测试。
评论
using
using
error: ... DECLARATIONS_WITH_NAMESPACES_USED_INCLUDED:: DECLARATIONS_WITH_NO_NAMESPACES_USED_INCLUDED::ClassName ...
关于“有没有办法撤消[声明]?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
评论
namespace
{}
{}
using namespace
评论
using namespace