【问题标题】:using declaration in header files在头文件中使用声明
【发布时间】:2014-04-07 18:11:27
【问题描述】:

我一直在寻找一些关于在头文件中使用 using-declarations 的说明(我四处寻找,但无法完全得到我正在寻找的答案)。到目前为止,我的研究得出的结论是,在 non-global 范围内使用它们是可以的,而命名空间指令则不好。我理解(至少我希望如此:))。

所以在我的示例中,我使用了shared_ptrs,但我需要支持在std:: 命名空间中没有它们但在std::tr1:: 中没有它们的旧编译器。由于使用shared_ptr 的每个类都需要相同的shared_ptr 定义,因此我必须在每个头文件中放置正确的#include 指令和使用声明。所以我把这部分移到了一个单独的头文件中,所以我只有一个需要更改的文件。使用哪个shared_ptr 的决定是通过预处理器指令HAS_SHAREDPOINTER 做出的,如果用户拥有支持std::shared_ptr 的编译器,则会设置该指令。

SharedPtr.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 的头文件中,我都包含这个头文件。例如在

ModelPar.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_ */

现在我认为我这样做的方式是错误的,因为包含我的任何头文件(使用 shared_ptrs)的用户在他的代码中也有相应的 using 声明。这是坏事,因为用户不知道这一点……等等。所以我将 using 声明放在全局范围内。要么?我对如何正确执行此操作感到困惑和困惑?提前致谢!

【问题讨论】:

    标签: file header declaration using


    【解决方案1】:

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

    SharedPtr.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_ */
    

    ModelPar.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_ */
    

    【讨论】:

    • 可能是风格偏好的问题,但是.... 在namespace blub 中定义所有使用条件shared_ptr 的东西是不必要的,而且不太直观。并考虑在structs 中声明类型别名的频率是有利的(例如,用于模板中),不能重新打开定义作为类型名的快捷方式。因此,据我所知,一种更惯用的方法是使用包含它的 namespaceclass 来限定别名的所有使用:struct MyTypes { using shared_ptr = std::shared_ptr; }; /*...*/ std::set&lt; MyTypes::shared_ptr&lt;ModelPar&gt; &gt;
    【解决方案2】:

    我个人认为在任何标题上使用“使用”没有任何好处。 曾经

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

    当然,无论名称冲突如何,您都可以使用一些预处理器魔法来完成它。但为什么?如果您遇到命名空间冲突,则说明您的方法有问题,绕过它就像关闭火警并声称不再发生火灾一样好。

    作为额外的奖励,它还掩盖了您的班级的祖先,例如“我是使用 X 命名空间中的 FooClass 吗?还是来自 Y?”。

    【讨论】:

    • 嗨曼努埃尔,嗯,我明白你的意思并同意将它放在头文件中没有意义,而只是放在源文件中。通常这就是我所做的,但否则我怎么能解决这个问题呢?不幸的是,我的项目不需要 c++11,所以我必须适应....
    • 在您的标题中,您需要使用您正在使用的类的完整声明。喜欢std::set&lt;std::tr1::shared_ptr&lt;ModelPar&gt;&gt; connections;。看起来你想要的是一个单一的位置来管理你正在使用的实现;为此,您可以使用包装器包装共享指针,因此使用它看起来像 std::set&lt;stdwrapper::my_shared_ptr&lt;ModelPar&gt;&gt; connections;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多