首页 文章

c头中的“using namespace”

提问于
浏览
105

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

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

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

还有一个问题沿袭相同的问题:头文件 #include 应该是所有与 .cpp 文件相对应的头文件,只需要头文件定义所需的头文件,让 .cpp 文件 #include 其余的,或者没有,并声明它需要的所有内容为 extern
问题背后的原因与上面相同:在包含 .h 文件时,我不希望出现意外 .

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

谢谢 .

9 回答

  • 21

    在 Headers 内包含 Headers 时需要注意 . 在大型项目中,它可以创建一个非常纠结的依赖链,触发比实际需要更大/更长的重建 . 查看this articleits follow-up以了解有关C项目中良好物理结构重要性的更多信息 .

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

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

  • 4

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

    GSFC C编码标准说:

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

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

  • 97

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

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

  • 3

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

  • 6

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

    Headers 应该只包含它需要编译的 Headers . 强制执行此操作的一种简单方法是始终包含每个源文件's own header as the first thing, before any other headers. Then the source file will fail to compile if the header isn' t自包含 . 在某些情况下,例如,引用库中的实现详细信息类,您可以使用前向声明而不是 #include ,因为您可以完全控制此类前向声明的类的定义 .

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

  • 3

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

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

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

  • 3

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

    只要你在项目范围内做出决定(“我们的项目广泛使用STL,我们不想在std :: . 之前添加所有内容 . ”),我没有看到它的问题 . 毕竟,你唯一担心的是名称冲突,以及无处不在的STL这不太可能是个问题 .

    另一方面,如果它是一个开发人员在单个(非私有)头文件中的决定,我可以看到它将如何在团队之间产生混淆,应该避免 .

  • 12

    我相信如果你在一个嵌套的命名空间中编写声明,你可以安全地在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编译器上测试过它 .

  • 5

    关于“是否有某种方法可以撤消[ 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 声明的范围,其效果仅在该范围内;当范围结束时,它是'undone' .

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

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

相关问题