如何转发声明用作成员变量的结构体

发布于 2024-11-27 21:48:48 字数 1119 浏览 1 评论 0原文

我在 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 成为一个指针来解决这个问题,这通常是我所做的,但是还有其他更合适的方法来解决这个问题吗?

I have a struct called CardState defined in Application.h:

#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[]);

}

I then use this CardState type in a different file:

#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

At the time Session.h is included it seems that Application.h has not yet been included so I need to forward declare the struct (see above). However, this is not enough, after having added the forward declaration, I still get this error:

'Session::cardState_' uses undefined struct 'CardState'

Which, if I understand correctly, means that the compiler doesn't know how to initialize my variable since CardState is only partially declared. I know I can fix this by making CardState a pointer, and that's usually what I do, but is there any other, more proper way, to fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

姐不稀罕 2024-12-04 21:48:48

根据 Oli Charlesworth 的评论,这应该按原样进行。

在一般情况下,您可能需要:

  • CardState 放入其自己的标头中,然后将其 #include 到所有“客户端”标头中,从而避免因这些标头的包含顺序而可能出现的任何复杂情况。
  • Session::cardState_ 声明为(智能)指针,并避免需要实际的 CardState 声明。

-- 编辑 ---

既然您编辑了代码,很明显,毕竟存在循环包含依赖项,在这种情况下您的代码确实无法工作,因此您必须应用上述解决方案之一。

As per Oli Charlesworth's comment, this should work as it is.

In general case, you would want to either:

  • Put CardState in its own header and then #include it in all "client" headers, thus avoiding any complications that might arise from include order of these headers.
  • Declare Session::cardState_ as a (smart) pointer and avoid need for actual CardState declaration.

-- EDIT ---

Now that you edited the code, it is clear that there are circular include dependencies after all, in which case your code really isn't going to work, so you must apply one of the solutions above.

十六岁半 2024-12-04 21:48:48

您有循环依赖项,循环依赖项是通过使用前向声明来解决的。

一旦你向前声明,编译器就只知道该类型存在;它没有任何关于其大小、成员或方法的信息。它被称为不完整类型。因此,您不能使用此类型(不完整类型)来声明成员或基类,因为编译器需要知道该类型的布局。

所以是的,您必须将 Incomplete 类型设置为指针。

You are having circular dependencies, Circular dependencies are solved by using forward declarations.

Once you forward declare the compiler only knows that the type exists; it does not have any information about its size, members, or methods. it is called an Incomplete type. Therefore, you cannot use this type(Incomlpete type) to declare a member, or a base class, since the compiler would need to know the layout of the type.

So Yes, You will have to make the Incomplete type a pointer.

笛声青案梦长安 2024-12-04 21:48:48

好的。首先,您不需要在这里转发声明任何内容,因为您需要的结构已在该头文件中完全声明。

当您尝试这样做时,最终会收到错误,可能是因为编译器认为您正在声明 CardState 的新版本,然后它永远不会在任何地方获得完整的声明。

您需要做的是删除 CardState 的第二个(存根)声明,然后修复导致您(错误地)放入该存根声明的错误。

在注释中,您说的是原始错误消息类似于“找不到标题”。对我来说,这意味着您的编译器的标准搜索库中可能没有包含 Application.h 的目录。如果您愿意,可以在命令行上使用 -I dirname 指令添加它。但很可能它与您的其他包含文件位于同一目录中,您只需将包含语句更改为以下内容即可找到:

#include "Application.h"  // Note quotes instead of <> 

更新:Laurent 更新了示例代码,并特别询问在下面关于指针的评论中。

首先,即使在更新的代码中,我也看不出为什么需要前向声明。只需将 CardState 的声明移至 Session.h 中,问题就会消失。像这样移动代码应该始终是您的第一个解决方案。当您具有相互引用的结构时,实际上仅需要前向引用。

如果确实有相互引用的结构,那么是的,您必须至少将这些字段之一设为指针或引用。这实际上并不是为了编译器,而是为了在物理上可以实现结构。如果 A 物理上包含 B 的完整副本,并且 B 物理上包含 A 的完整副本,则从逻辑上讲,您的结构将具有无限大小!

OK. First off, you don't need to forward declare anything here, because the struct you need is fully declared in that header file.

When you try to do it anyway, you end up getting an error, probably because the compiler thinks you are declaring a new version of CardState, and then it never gets the full declaration anywhere.

What you need to do is remove that second (stub) delcaration for CardState, and then fix the error that led you to (mistakenly) put that stub declaration in.

In the comments you say that original error message was something like "couldn't find header". To me that means you probably don't have the directory containing Application.h in you compiler's standard search library. You can add it with a -I dirname directive on the command line if you like. But most likely it is in the same directory as your other include file, and you can just change your include statement to the following and it will be found:

#include "Application.h"  // Note quotes instead of <> 

Update: Laurent updates the example code, and specifically asked in the comments below about pointers.

First off, even in the updated code, I see no reason why the forward declaration is requred. Simply move CardState's declaration into Session.h, and the problem would go away. Moving code around like this should always be your first solution. Forward references are really only required when you have mutually-referencing structures.

If you do indeed have mutually-referenceing structures, then yes, you will have to make at least one of those fields either a pointer or a reference. This isn't really for the compiler so much as it is so that its physically possible to implement the structure(s). If A physically contains a full copy of a B and B physically contains a full copy of an A, then your structure would logically be of infinite size!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文