c ++标题中的"using namespace"

Bar*_*uch 115 c++ namespaces header-files

在我们所有的C++课程,所有的老师总是把using namespace std;在之后#include在它们的S .h文件.从那时起,我觉得这很危险,因为在另一个程序中包含该标题我会将命名空间导入到我的程序中,可能没有意识到,打算或想要它(标题包含可以非常深入嵌套).

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

//header.h
using namespace std {
.
.
.
}
Run Code Online (Sandbox Code Playgroud)

还有一个问题是:标题文件是否应该是#include相应.cpp文件所需的所有标题,只有那些标题定义所需的标题,并让.cpp文件#include为其余标题,或者没有,并声明它需要的所有内容extern
问题背后的原因与上面相同:在包含.h文件时我不想要惊喜.

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

谢谢.

Mar*_*k B 111

你绝对不应该using namespace在标题中使用它,因为它可以意外地改变包含该标题的任何其他文件中代码的含义.没有办法撤消using namespace这是另一个如此危险的原因.我通常只是使用grep或类似的东西,以确保using namespace没有在标题中调出,而不是尝试任何更复杂的东西.可能静态代码检查器也会标记这一点.

标题应该只包含它需要编译的标题.一种简单的方法是在任何其他标头之前始终将每个源文件自己的标头包含在内.如果标头不是自包含的,则源文件将无法编译.在某些情况下,例如,引用库中的实现详细信息类,您可以使用前向声明,而不是#include因为您可以完全控制此类前向声明​​的类的定义.

我不确定我会把它称为常见,但它肯定会偶尔出现,通常是由不了解负面后果的新程序员编写的.通常只需要对风险进行一点教育即可解决任何问题,因为修复起来相对简单.

  • 我们可以在`.cpp`文件中自由使用`using`语句吗?`3rdPartyLib :: BigClassName <3rdPartyLib :: AnotherBigName,3rdPartyLib :: AnotherBigName> :: Iterator是触手可及的死亡. (2认同)
  • 我们应该如何简化应该位于标题中的“模板”函数?`typedef`? (2认同)

And*_*mas 25

Sutter和Alexandrescu的"C++编码标准:101规则,指南和最佳实践"中的第59项:

  1. 不要在头文件中或#include之前编写命名空间.108

所有指南的标题都在http://www.gotw.ca/publications/c++cs.htm,但细节是C++开发人员必读的内容.


Mik*_*nor 12

在标头内包含标头时需要注意.在大型项目中,它可以创建一个非常纠结的依赖链,触发比实际需要更大/更长的重建.看看这篇文章其后续更多地了解良好的物理结构的C++项目的重要性.

在绝对需要时(只要需要完整定义类),您应该只在头部中包含标头,并在任何可能的地方使用前向声明(当需要类时是指针或引用).

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

  • 如何简化“模板”函数声明?这必须出现在标题中,不是吗? (3认同)
  • +1尽可能强调前瞻性声明. (2认同)

You*_*ohn 7

关于“有没有办法撤销[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
Run Code Online (Sandbox Code Playgroud)

如此有效,是的。通过限制using声明的范围,其效力仅在该范围内持续;当该范围结束时,它被“撤销”。

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

在头文件的情况下,如果using声明在文件范围内,这将扩展到包含头文件的任何文件的范围。

  • 你似乎是唯一一个如何理解实际问题的人......但是,我的编译对我在类减速中使用并不是很满意。 (3认同)

Jon*_*ler 6

查看戈达德太空飞行中心编码标准(C和C++).结果比过去有点困难 - 请参阅SO问题的更新答案:

GSFC C++编码标准说:

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

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


Öö *_*iib 5

你是对的,using namespace在标题是危险的.我不知道如何撤消它.它很容易检测到,但只搜索using namespace头文件.出于这个最后的原因,它在实际项目中并不常见.如果有人做类似的事情,更有经验的同事很快就会抱怨.

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


AnA*_*ons 5

我相信,如果您在嵌套命名空间中编写声明,则可以安全地在 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;
Run Code Online (Sandbox Code Playgroud)

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

  • 这是我以前从未见过的有用技术;谢谢。通常,我很喜欢使用完整范围限定,并将“using”声明放在函数定义中,这样它们就不会污染函数外部的名称空间。但现在我想在头文件中使用 C++11 用户定义的文字,并且按照通常的约定,文字运算符受命名空间保护;但我不想在构造函数初始值设定项列表中使用它们,这些列表不在我可以使用无污染的“using”声明的范围内。所以这对于解决这个问题非常有用。 (2认同)