在c ++头文件中使用“命名空间”
在我们所有的c ++课程中,所有的老师总是using namespace std;
#include
在.h
文件中的#include
之后。 这似乎是危险的,因为通过在另一个程序中包含这个头文件,我会得到名字空间导入到我的程序,也许没有意识到,打算或想要(头包含可以非常深的嵌套)。
所以我的问题是双:我是正确的, using namespace
不应该在头文件中使用,和/或有一些方法来撤消它,如:
//header.h using namespace std { . . . }
还有一个问题应该是这样的:一个头文件应包含所有与.cpp
文件相对应的所有头文件,只有那些头文件定义需要的头文件,并且让.cpp
文件包含其余的,或者不包含所有头文件它需要作为extern
?
这个问题背后的原因与上面相同:包含.h
文件时,我不希望出现意外。
另外,如果我是对的,这是一个常见的错误? 我的意思是在现实世界的编程和在那里的“真实”的项目。
谢谢。
正如你所说,你绝对不应该在头文件中using namespace
,因为它可以意外地改变包含该头文件的任何其他文件中的代码含义。 有没有办法撤消using namespace
,这是另一个原因是如此危险。 我通常只是使用grep
或类似的东西,以确保using namespace
不被标题调出,而不是尝试任何更复杂的事情。 也许静态代码检查器也标记这一点。
头文件应该只包含需要编译的头文件。 执行此操作的一个简单方法是始终在每个源文件的头部之前包含每个源文件头。 那么如果头文件不是独立的,源文件将无法编译。 在某些情况下,例如引用库中的实现细节类,可以使用前向声明而不是#include
因为您可以完全控制这种前向声明类的定义。
我不确定我是否会把它叫做通用的,但它肯定会偶尔出现,通常由不知道负面影响的新程序员写出来。 通常只要对风险进行一点教育就可以解决任何问题,因为修复起来相对简单。
Sutter和Alexandrescu的“C ++编码标准:101规则,指南和最佳实践”中的第59项:
- 不要在头文件中或在#include之前编写名称空间。 108
所有指南的标题都在http://www.gotw.ca/publications/c++cs.htm ,但细节是C ++开发人员必读的。
将标题包含在标题中时需要小心。 在大型项目中,它可以创build一个非常纠结的依赖链,触发比实际需要更大/更长的重build。 查看本文 及其后续内容,以更好地了解C ++项目中良好物理结构的重要性。
当绝对需要时(只要需要完全定义一个类的定义),应该只在头文件中包含头文件,并且可以在任何地方使用前向声明(当需要的类是指针或引用时)。
至于命名空间,我倾向于在我的头文件中使用显式命名空间范围,只在我的cpp文件中放置一个using namespace
。
查看戈达德太空飞行中心编码标准(适用于C和C ++)。 事实certificate,这比以前要困难一些 – 查看对于SO问题的更新答案:
- 我应该在头文件中使用#include吗?
- C和C ++中的自给自足头文件
GSFC C ++编码标准说:
§3.3.7每个头文件应包含它需要编译的文件,而不是强制用户
#include
包括所需的文件。#includes
只限于标题所需的内容; 其他#includes
应该放在源文件中。
现在交叉参考的第一个问题现在包括GSFC C编码标准的引用和基本原理,但实质结果是相同的。
在头中using namespace
是很危险的。 我不知道如何撤消它。 它很容易检测到,但只是在头文件中using namespace
进行search。 由于最后的原因,在实际的项目中是不常见的。 如果有人做了类似的事情,更有经验的同事也会很快抱怨。
在真实的项目中,人们尽量减less包含文件的数量,因为包含的文件越less编译速度就越快。 这节省了大家的时间。 但是,如果头文件假定在它之前应该包括一些东西,那么它应该包含它自己。 否则,它使标题不是自包含的。
你是对的。 而任何文件只能包含该文件所需的头文件。 至于“在现实世界的项目中是否做错了共同点?” – 哦,是的!
像编程中的所有事情一样,实用主义应该胜过教条主义,海事组织。
只要你在项目范围内作出决定(“我们的项目广泛地使用STL,而且我们不想用std ::来做任何事情)”,我不认为它有问题。 唯一冒着冒险的是名称冲突,毕竟STL无处不在,这不太可能是个问题。
另一方面,如果这是一个开发人员在一个单独的(非私人的)头文件中做出的决定,我可以看到它会如何在团队中产生混淆,应该避免。
我相信你可以安全地在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编译器上testing过了。
关于“有没有办法撤销[ 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
声明在文件范围内,这将扩展到包含头的任何文件的范围。