开发者

How to forward declare a structure used as a member variable

开发者 https://www.devze.com 2023-03-25 16:30 出处:网络
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

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 p开发者_如何学Pythonroperty2;
};

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?


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.


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.


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!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号