C++ 强制对C++;Mac上的代码(使用Xcode)

C++ 强制对C++;Mac上的代码(使用Xcode),c++,xcode,macos,include,forward-declaration,C++,Xcode,Macos,Include,Forward Declaration,这是一个奇怪的问题,我想知道是否有人见过。我们正在为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的正向声明,

这是一个奇怪的问题,我想知道是否有人见过。我们正在为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文件中定义的templates方法,而该方法引用了另一个类中的方法,那么编译器对此一无所知。类似地,如果我们引用在包含的类中定义的枚举,编译器将无法识别它(解决此问题的方法是将该枚举放在单独的.h文件中,并且它很好地拾取了它)

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

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

非常感谢…

对于您的第一期(类),正确的答案是使用转发声明。应避免在其他项目包含文件中包含项目包含文件。这可以创建include循环(如果我不得不猜测的话,这很可能是您的问题)。当您修改标头时,它也会产生过多的构建搅动

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


有关此问题和最佳做法的更多讨论,请参阅。

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


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

我很惊讶,没有人提到过包含文件的规范方案,例如

。 foo.h:

#ifndef FOO_H
#define FOO_H
// body of the include file
#endif
我怀疑在这个特定的案例中,“x.h”和“x.h”的冲突可能是您看到的问题,但是如果您不像这样保护include文件,它最终会咬到您


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

#包含“x.h”
包含“x.h”
?您是否收到任何警告,如“未能找到'X.h'”?您是否可以发布一个实际的最小示例来说明您遇到的问题(包括cpp文件)?当我试图编译您的头文件时,编译器正确地抱怨您的类声明末尾缺少分号。当我修复这个问题时,代码可以在Mac OS下使用GCC4.2进行良好编译。(我怀疑您的实际头文件包含include guard或
#pragma once
,您的问题与此相关。)您可能希望查看是否有一个X.h头的旧副本,编译器正在读取该副本,而不是最新的头。头存储在哪里?选中“项目设置”“生成”选项卡。向下滚动至搜索路径部分,确保可以找到您的标题。另外,请阅读“始终搜索用户路径”的帮助,尽管这可能与主题无关。记住苹果默认文件系统不区分大小写,这一点很重要。因此,“X.h”和“X.h”是相同的文件名。由于X显示为Y的值成员,因此Y.h中的转发声明(仅)不合适。需要X的完整定义。在这种情况下,您是绝对正确的。如果可能的话,您应该避免包含,但正如您所注意到的,在这种情况下是不可能的。