【问题标题】:C++: include multiple header files with same name from different namespacesC ++:包含来自不同名称空间的多个具有相同名称的头文件
【发布时间】:2010-09-10 20:06:27
【问题描述】:

如何解决通过包含一个与另一个头文件同名的头文件而创建的问题,该头文件已因另一个包含而间接包含?

例如:

// src/blah/a.hpp
#ifndef A_HPP
#define A_HPP

namspace blah
{

class A
{
}

}

#endif

// src/blah/b.hpp
#ifndef B_HPP
#define B_HPP

#includes "a.hpp"

namspace blah
{

class B
{
}

}

#endif

// src/foo/a.hpp
#ifndef A_HPP
#define A_HPP

namspace foo
{

class A
{
}

}

#endif

// src/foo/c.hpp
#ifndef C_HPP
#define C_HPP

#includes "../b.hpp"
#includes "a.hpp"       // won't be included due to multiple inclusion prevention

namspace foo
{

class C
{
}

}

#endif

在最后一个头文件中,a.hpp 不会被包含,因为多重包含预处理器保护。确实,这应该没问题,因为这些类位于不同的名称空间中。我意识到最简单的方法是更改​​ foo/a.hpp 的名称,或者只是在多重包含保护中给它一个假名称。有没有更好的办法?

编辑 我了解您可以通过在 #define 和 #ifndef 指令中使用更具描述性的名称(例如 FOO_A_HPP 和 BLAH_A_HPP)来解决此问题,但我想知道这是否是推荐或最佳方式。有些人会建议使用不同的文件名作为更好的解决方案,还是真的不重要?你会推荐使用约定吗:

<NAMESPACE>_<CLASS>_HPP

而不是

<CLASS>_HPP

为了更好地避免这些问题?

【问题讨论】:

  • 为什么这被标记为C?
  • 我总是把命名空间放在我的守卫中。自动化工具会将 GUID 作为标头保护。重点是它们必须是唯一的(不仅在您的项目中,而且如果可能的话,最好在全世界所有文件中的所有维度上都是唯一的)。

标签: c++ header include


【解决方案1】:

您可以简单地解决这个问题,方法是不在顶部使用相同的#define ...

最好使用 BLAH_A_HPP 和 FOO_A_HPP 等,以便 #define 也包含命名空间名称。

编辑:我个人建议执行以下操作:

1) 不要将标题命名相同(即使用不同的文件名...这并不总是有帮助)并使用不同的#define 名称..
2)不要为类命名相同的东西。每个标题放置 1 个类,并在类后命名标题
3) 如果它们由命名空间区分,则在文件名中使用该命名空间 AND #define
4) 为您添加一个 ID #define,它对您来说是独一无二的(例如,我可以使用 GOZ)
5) 使用#pragma 一次。它对编译器很有用。

不过,这完全是口味问题。选择一个适合你的方案并坚持下去。没有对错之分。只要它有效并且是一致的。

【讨论】:

  • 了解,请参阅我的编辑以获取有关该问题的更多说明。您一般会推荐 NAMESPACE_CLASS_HPP 的约定吗?这比仅更改文件名更好还是无关紧要?
  • @deuberger:更改文件名不会有任何区别;问题是由于重复的包含警卫名称。是的,我建议使用 NAMESPACE_CLASS_HPP 之类的东西作为包含保护。
  • 确实它是一个“部分解决方案”......我会修复它:)
【解决方案2】:

我很惊讶没有人提到下面使用#undef A_HPP的简单解决方案

//src/foo/c.hpp
#ifndef C_HPP
#define C_HPP

#includes "../b.hpp"
#undef A_HPP
#includes "a.hpp" 
...

如果 foo/c.hpp 是唯一可以或被允许更改的文件,这将特别好。

【讨论】:

    【解决方案3】:

    当 MSVC 创建一个类时,它会在您的保护名称中添加一个 GUID 以避免此类问题。

    【讨论】:

    • 这里没有说他使用 MSVC,因为它是 C++,所以无论如何都是不可能的。
    • @mathepic:你的意思是什么是不可能的,因为它是 C++,这是什么废话?举一个标准方法的例子,以确保标头保护具有独特的背景,而不是说使用 MSVC 是必要的。
    • @mathepic:不,它绝对包括 C++,这仍然不是重点。
    【解决方案4】:

    虽然C 中没有命名空间,但我认为这对CC++ 都有效。

    #ifndef BLAH_B_HPP
    

    #ifndef FOO_B_HPP
    

    【讨论】:

      【解决方案5】:

      正如您自己建议的那样,执行此操作的正常方法是通过附加 GUID、完整路径或您拥有的东西来使您的警卫标识符唯一。

      在 VC++ 中还有一个 pragma 来为你处理多重包含,所以你不需要自己写 #if defined(HUMPTYDUMPTY) 位,就像

      #pragma once
      

      现在已经有几次 VC++ 迭代,但对于其他编译器,您需要检查。这也省去了寻找唯一名称的麻烦。

      已编辑: 刚看了一下,互联网认为这也在 GCC 中。看起来#include 风格的守卫很像 20 世纪......

      【讨论】:

      • 好点,虽然它看起来像#pragma 一般和#pragma once 不是首选方式。请参阅:stackoverflow.com/questions/787533/…
      • 只需阅读有关编译指示的帖子。我并不担心这里的表现;只是认为你输入的越多,你出错的可能性就越大。但是,如果您在不兼容的编译器之间进行大量代码移植,则可能会出现问题。无论哪种方式,我都不会为此失眠。
      猜你喜欢
      • 2018-06-25
      • 2014-01-12
      • 2020-06-28
      • 2017-05-13
      • 2020-03-30
      • 2011-05-29
      • 1970-01-01
      • 2011-09-16
      • 2022-06-14
      相关资源
      最近更新 更多