我在 Application.h :
中定义了一个名为CardState
的结构
#ifndef APPLICATION_H
#define APPLICATION_H
#include <Session.h> // Note that both files include each others
struct CardState {
bool property1;
bool property2;
};
class Application : public QApplication {
Q_OBJECT
public:
explicit Application(int argc, char *argv[]);
}
然后我在另一个文件中使用此CardState
类型:
#ifndef SESSION_H
#define SESSION_H
#include <Application.h>
struct CardState;
class Session : public QObject {
Q_OBJECT
public:
void setCardState(const CardState& cardState);
CardState cardState() const;
private:
CardState cardState_;
};
}
#endif // SESSION_H
当包含 Session.h 时,似乎还没有包含 Application.h 所以我需要转发声明结构(参见上文)。但是,这还不够,在添加了前向声明之后,我仍然会收到此错误:
'Session::cardState_' uses undefined struct 'CardState'
如果我理解正确,那意味着编译器不知道如何初始化我的变量,因为CardState
只是部分声明。我知道我可以通过使CardState成为指针来解决这个问题,而这通常就是我所做的,但还有其他更合适的方法来解决这个问题吗?
答案 0 :(得分:4)
根据Oli Charlesworth的评论,这应该可以正常使用。
一般情况下,您可能想要:
CardState
放在自己的标题中,然后在所有“客户端”标题中#include它,从而避免因这些标题的包含顺序而产生的任何复杂情况。Session::cardState_
声明为(智能)指针,避免需要实际的CardState
声明。- 编辑---
现在您已经编辑了代码,很明显存在循环包含依赖项,在这种情况下,您的代码确实不起作用,因此您必须应用上述解决方案之一。
答案 1 :(得分:1)
行。首先,您不需要在此处转发声明任何内容,因为您需要的结构在该头文件中完全声明。
无论如何,当你尝试这样做时,你最终会收到错误,可能是因为编译器认为你正在宣布新版本的CardState
,然后它永远不会在任何地方获得完整的声明。
您需要做的是删除CardState
的第二个(存根)延期,然后修复导致您(错误地)将该存根声明放入的错误。
在评论中,您说原始错误消息类似于“找不到标题”。对我而言,这意味着您可能没有编译器标准搜索库中包含Application.h
的目录。如果您愿意,可以在命令行上使用-I dirname
指令添加它。但很可能它与您的其他包含文件位于同一目录中,您只需将include语句更改为以下内容即可找到它:
#include "Application.h" // Note quotes instead of <>
更新:Laurent更新了示例代码,并在下面的评论中特别询问了指针。
首先,即使在更新的代码中,我也没有理由要求提出前向声明。只需将CardState
的声明移到Session.h中,问题就会消失。像这样移动代码应始终是您的第一个解决方案。当你有相互引用的结构时,前向引用实际上只是 required 。
如果你确实有相互引用的结构,那么是的,你必须使这些字段中的至少一个成为指针或引用。这对编译器来说并不是真正的,因为它实际上可以实现结构。如果A
实际上包含B
的完整副本且B
实际上包含A
的完整副本,那么您的结构在逻辑上将具有无限大小!
答案 2 :(得分:1)
您具有循环依赖关系,循环依赖关系通过使用前向声明来解决。
一旦你转发声明,编译器只知道该类型存在;它没有关于其大小,成员或方法的任何信息。它被称为不完整类型。因此,您不能使用此类型(Incomlpete类型)来声明成员或基类,因为编译器需要知道该类型的布局。
是的,您必须将不完整类型作为指针。