【问题标题】:Forced to use forward declarations for C++ code on Mac (using Xcode)强制在 Mac 上对 C++ 代码使用前向声明(使用 Xcode)
【发布时间】:2012-03-31 03:54:08
【问题描述】:

这是一个奇怪的问题,我想知道其他人是否见过。我们正在为 Mac 和 PC 编写跨平台的 C++ 代码,而这只发生在 Mac 上。

假设我有一个类,其 .h 文件如下所示。

class X {
public:
    int _myValue;
    void myFunction();
}

我还有另一个类,其 .h 文件如下所示:

#include "X.h"
class Y {
private:
     X _myObj;
}

这不会编译。我们得到一个错误,表明 X 未定义。解决方法是在Y.h文件中为X添加前向声明,如: X 类;

我们已经这样做了一段时间,但现在我们遇到了它运行不佳的情况。例如,如果我们有一个 .h 文件,该文件在 .h 文件中定义了一个模板方法,并且该方法引用了另一个类中的方法,则编译器对此一无所知。同样,如果我们引用在包含的类中定义的枚举,编译器将无法识别它(此问题的解决方法是将枚举放在单独的 .h 文件中,它可以很好地拾取它)。

就好像在编译 .cpp 文件时,编译器没有从包含的 .h 文件中提取数据。

我只是想知道是否有人见过这样的事情,或者有可能的调查途径。

非常感谢...

【问题讨论】:

  • #include "X.h"'include "x.h"?您是否收到任何警告,例如“未能找到 'X.h'”?
  • 您能否发布一个实际的最小示例来展示您遇到的问题(包括 cpp 文件)?当我尝试编译你的头文件时,编译器正确地抱怨你的类声明最后缺少分号。当我解决这个问题时,代码在 Mac OS 下使用 gcc 4.2 编译得很好。 (我怀疑您的实际头文件包含包含警卫或#pragma once,并且您的问题与此有关。)
  • 你可能想看看你是否有一个 X.h 头文件的旧副本,它正在被编译器而不是最新的头文件拾取。
  • 标头存储在哪里?检查您的项目设置构建选项卡。向下滚动到“搜索路径”部分,确保可以找到您的标题。另请阅读始终搜索用户路径的帮助,尽管这可能不是主题。
  • 重要的是要记住 Apple 默认文件系统不区分大小写。所以“X.h”和“x.h”是同一个文件名。

标签: c++ xcode macos include forward-declaration


【解决方案1】:

对于您的第一个问题(类),正确的答案是使用前向声明。您应该避免在其他项目包含文件中包含项目包含文件。这可以创建包含循环(如果我不得不猜测,这很可能是您的问题)。当您修改标头时,它还会造成过多的构建流失。

对于您的其他问题(枚举、模板),这通常是由于包含循环。通过尽可能避免包含来打破这些循环是您最好的选择。

有关此问题和最佳实践的更多讨论,请参阅Header file best practices for typedefs

【讨论】:

  • Y.h 中的前向声明(仅)不合适,因为 X 显示为 Y 的值成员。需要 X 的完整定义。
  • 在这种情况下你是绝对正确的。您应该避免包含 如果可能,但正如您所指出的,在这种情况下是不可能的。
【解决方案2】:

有一个通用的系统头文件X.h,它是 X11 窗口工具包的一部分。我建议更改头文件的名称,以免与任何系统头文件冲突。

您可以尝试更改编译器开关以强制它在系统包含目录之前考虑包含头文件的目录,但这可能更费力且更脆弱。

【讨论】:

    【解决方案3】:

    我只是有点惊讶,没有其他人提到包含文件的规范方案,例如,

    foo.h:

    #ifndef FOO_H
    #define FOO_H
    // body of the include file
    #endif
    

    我怀疑在这种特定情况下,“xh”和“Xh”的冲突可能是您看到的问题,但如果您不保护这样的包含文件,它 最终咬你。

    有了这个守卫,你可以在任何你需要的地方包含“x.h”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多