【问题标题】:Can a mixed C/C++ header include another mixed header?混合 C/C++ 标头可以包含另一个混合标头吗?
【发布时间】:2014-09-30 14:58:43
【问题描述】:

在阅读Why do we need extern "C"{ #include <foo.h> } in C++? 之后,我得出结论,在 extern "C" 块中包含一个标题是可以的。

但是我遇到了这个星座的问题:

#ifdef __cplusplus
extern "C" {
#endif

#include "mixedstuff.h"

#ifdef __cplusplus
}
#endif

mixedstuff.h:

#ifdef __cplusplus
extern "C" {
#endif

#include "cstuff.h"

#ifdef __cplusplus
}
#include "cppstuff.h"
#endif

正如大家所见,我最终将cppstuff.h 包含在extern "C" 块中的C++ 编译器中。这导致了很多错误,因为很多语句都不能使用 C-linkage。

显而易见的解决方案是在extern "C" 块之外添加#include mixedstuff.h。但这需要我查看每个标题,看看它是普通的 C、C++ 还是混合的。

据此,我建议使标头可以识别 C++,而不是将它们包含在 extern "C" 中。我是对的,还是有更好的方法?

【问题讨论】:

  • 第一次使用 __cplusplus 是不必要的,因为包含的 .h 文件已经处理了它。这当然解决了问题。不要帮助太多:)
  • 这就是我所说的“显而易见的解决方案”。我试图为这种情况寻求最佳实践。

标签: c++ c c-preprocessor


【解决方案1】:

根据您的描述,我推测mixedstuff.h 是设计的 在 C 和 C++ 中都可以使用。这意味着它可能有 #ifdef __cplusplus 等,在一些地方有一些纯 C++ 代码。 在这种情况下,它应该包含在extern "C" 块中。一般来说,除非另有明确说明, 大多数标题应包含在最外层,外部 所有块、命名空间等。一个例外是纯粹的 C 头文件,作者尚未将库设计为 从 C++ 使用;这些必须包含在extern "C" 中 堵塞。 (但据我所见,这样的标题越来越少 并且更罕见。)

而且您不必查看标题内部;您需要查看文档。

如果您是标头的作者,那么您应该让它知道 C++(并记录这一事实,也许在库级别)。

【讨论】:

    【解决方案2】:

    当示例告诉您将extern "C" 放入自己时,即包含仅 C 标头。

    由于它是纯 C 语言,它可能是用 C 语言为 C 编写的,所以如果你想将它用于 C++,你需要将它指定为 C 头文件。

    如果您有mixstuff.h,它将无法在 C 中工作,因为它只有 C++ 结构。那些是您希望通过 C 链接拥有的 C 构造,您应该在 mixstuff.h 中明确标记。或者将它们隔离到自己的标题中。

    请注意,与mixstuff.h 一起,在某个地方会编译一个mixstuff.cmixstuff.cpp,甚至可能有两个不同的编译单元。您可以使用 C++ 编译器来编译实现,它们甚至可以是 C++(带有 C 链接),在其实现中使用 C++ 构造(通常是。您通常会为您的 C++ 库提供 C 接口)。

    如果 mixstuff 最初是在 C++ 中构建的,并且带有 C++ 名称修饰,如果您现在将 extern "C" 放在其声明周围,它将不会与您的代码链接。如果这些函数确实是由 C 编译器构建的,则需要使用 extern "C" 才能看到它们。

    【讨论】:

      【解决方案3】:

      C和C++标准多种多样,有共同点,也有不同。

      如果代码是在所有目标标准的公共交集中编写的,只需将其包含在全局命名空间中即可。

      如果在 C++ 中包含时仅缺少 extern "C",则将其包装在外部。

      否则事情会变得复杂,你必须直接修补它。

      预处理器具有__cplusplus__STDC_VERSION__ 和其他功能和语言测试宏的条件,是一种编写代码的方法,该代码在比通用语言本身所保证的更广泛的条件下正常运行。

      明智地使用它,它很容易被误用。

      【讨论】:

      • +1 表示“明智地使用它,它很容易被误用”。我现在已经阅读了一些关于 extern "C"-construct 的内容,并没有发现这样的警告词。
      【解决方案4】:

      如果您想确保内容具有 C++ 链接,即使包含的头文件可能包含在 extern "C" 块中,您可以使用 extern "C++" 块:

      extern "C++" {
      #include "cppstuff.h"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多