代码之家  ›  专栏  ›  技术社区  ›  steve

在头文件中使用声明

  •  3
  • steve  · 技术社区  · 10 年前

    我一直在寻找关于 使用声明 在头文件中(我在四处搜索,但找不到我想要的答案)。我的研究得出的结论是 非全局的 作用域正常,而命名空间指令不正确。我明白(至少我希望如此)。

    所以在我的例子中,我使用 shared_ptr s、 但我需要支持在 std:: 命名空间,但在 std::tr1:: 例如由于每个类都使用 共享ptr 需要相同的 共享ptr 我必须把正确的 #include 指令和using声明。所以我把这个部分移到了一个单独的头文件中,所以我只有一个文件需要修改。决定 共享ptr 使用,通过预处理器指令进行 HAS_SHAREDPOINTER ,如果用户的编译器支持 std::shared_ptr .

    共享Ptr.h :

    #ifndef SHAREDPTR_H_
    #define SHAREDPTR_H_
    
    #ifdef HAS_SHAREDPOINTER
    #include <memory>
    using std::shared_ptr;
    #else
    #include <tr1/memory>
    using std::tr1::shared_ptr;
    #endif
    
    #endif /* SHAREDPTR_H_ */
    

    现在,在使用shared_ptr的每个头文件中,我都包含了这个头文件。例如,在

    型号Par.h :

    #ifndef MODELPAR_H_
    #define MODELPAR_H_
    
    #include <string>
    #include <set>
    
    #include "SharedPtr.h"
    
    class ModelPar {
      private:
        std::set<shared_ptr<ModelPar> > connections;
      ...
    };
    
    #endif /* MODELPAR_H_ */
    

    现在我认为我这样做是错误的,因为包含我的任何头文件的用户(使用 共享ptr s) 也具有相应的 使用声明 在他的代码中。这是一件坏事,因为用户没有意识到这一点。。。所以我将使用声明放在全局范围内。或我有点困惑,不知道该怎么做?提前感谢!

    2 回复  |  直到 8 年前
        1
  •  1
  •   steve    10 年前

    好的,我自己找到了答案。我想我没有意识到命名空间中的using声明在以下同名命名空间范围中仍然有效。现在,Bjarne的话也更有意义,即不应污染全局命名空间:)。如果我仍然做错了什么,请纠正我。

    共享Ptr.h:

    #ifndef SHAREDPTR_H_
    #define SHAREDPTR_H_
    
    #ifdef HAS_SHAREDPOINTER
    #include <memory>
    namespace blub {
    using std::shared_ptr;
    }
    #else
    #include <tr1/memory>
    namespace blub {
    using std::tr1::shared_ptr;
    }
    #endif
    
    #endif /* SHAREDPTR_H_ */
    

    型号Par.h:

    #ifndef MODELPAR_H_
    #define MODELPAR_H_
    
    #include <string>
    #include <set>
    
    #include "SharedPtr.h"
    
    namespace blub {
    
      class ModelPar {
      private:
        std::set<shared_ptr<ModelPar> > connections;
        ...
      };
    }
    
    #endif /* MODELPAR_H_ */
    
        2
  •  0
  •   Manuel    9 年前

    我个人看不到在任何标题上使用“using”有任何好处。 曾经 .

    这不仅使重新考虑变得极其困难,因为如果删除标头标头包含链,编译器错误将变得无用。获取300+个缺少声明、类型未定义等错误;这不完全是我对“娱乐时光”的定义。

    当然,您可以使用一些预处理器魔法来完成它,而不考虑名称冲突。但为什么?如果您有名称空间冲突,那么您的方法有问题,那么绕过它就像关闭火灾警报一样好,并声称不再发生火灾。

    作为一个额外的好处,它还模糊了你的类的起源,比如“我是从X命名空间使用FooClass吗?还是从Y命名空间使用?”。