Double include solution?
Asked Answered
T

3

3

In C++, I have a problem with a double include:

File stuffcollection.h

#pragma once
#ifndef STUFFCOLLECTION_H
#define STUFFCOLLECTION_H

#include "Stage.h"

class Stuffcollection {
    public:
        bool myfunc( Stage * stage );
};

#endif // STUFFCOLLECTION_H

File stage.h:

#pragma once
#ifndef STAGE_H
#define STAGE_H

#include "Stuffcollection.h"

class Stage {
    // stuffcollection used in stage.cpp
};

#endif // STAGE_H

Compiler Error:

\Stuffcollection.h|(line were bool myfunc is declared)|error: 'Stage' has not been declared| ||=== Build finished: 1 errors, 0 warnings ===|

Can someone please explain why this happens and how it can be solved? I already use include guards and the pragma once preprocessor directive and it just doesn't work.

(If I remove #include "Stuffcollection.h" from stage.h and comment out the respective lines that are using it in stage.cpp, the rest of my code works fine. It's really just when including Stuffcollection into stage that it suddenly stops working.)

PS: stage is just one example, I use stuffcollection in almost every other file too, and everytime I get this problem.

EDIT: I followed what has been suggested, and now the problem is invalid use of incomplete type, i.e. while the answers given solve the problem of the circular dependency they do not solve the problem I am dealing with. My problem is continued in Circular Dependencies / Incomplete Types.

EDIT: Both solved now.

Tassel answered 5/10, 2011 at 18:29 Comment(0)
P
14

You have a Circular Dependency. Instead use Forward Declaration in Stuffcollection.h

#pragma once
#ifndef STUFFCOLLECTION_H
#define STUFFCOLLECTION_H

//#include "Stage.h"      //<------------------Don't Do This
class Stage;              //<------------------Do This

class Stuffcollection {
    public:
        bool myfunc( Stage * stage );
};

#endif // STUFFCOLLECTION_H

Rationale:
You can use the forward declaration in above snippet because, Stuffcollection.h only uses pointer to Stage.

Explanation:
Using a forward declaration of class Stage, the compiler does not know the composition of it nor the members inside it, the compiler only knows that Stage is a type. Thus, Stage is an Incomplete type for the compiler. With Incomplete types , One cannot create objects of it or do anything which needs the compiler to know the layout of Stage or more than the fact that Stage is just an type. Since pointers to all objects need just the same memory allocation, You can use the forward declaration when just referring to Stage as a pointer.

You can use Forward Declarations to get over your circular dependency problems.

Further Read:
When to use forward Declarations?

Pub answered 5/10, 2011 at 18:31 Comment(6)
I maybe didn't make this clear enough, but I need to be able to create stuffcollection objects (or at least use methods of stuffcollection objects that were passed in) in stage and vice versa. Right now my problem is ´invalid use of incomplete type´.Tassel
@Ben: Your Q actually didn't mention any of it, Did you read the link? It will give you a complete list of what you can/t do with Incomplete types. If you have specific error case for Incomplete type post it as an Question.Pub
Sorry, but why would I inlcude it if I'm not going to use it. Thanks for your answer anyway, I guess it is the solution to the circuluar dependecy, just not to my problem in particular.Tassel
@Ben: I think so, Probably, You are just confusing two problems, Yes this is the solution for the circular dependency problem. For your other problem please post a new Question with details,that keeps the two distinct things separate and warrants you a proper solution.Pub
#7667165Tassel
@Ben: Do what I suggest in the answer on that Q, and it should be fine.Pub
O
6

It's a circular dependency. Don't make them. This one you can resolve by replacing #include "Stage.h" in stuffcollection.h with a forward declaration of Stage (i.e. class Stage;).

Opprobrious answered 5/10, 2011 at 18:31 Comment(1)
This is worth +1 for the sound advice in the first two sentences.Horsa
A
3

Instead of the #include you can use forward declarations i.e. class Stage; and class Stuffcollection. It also has the benefit of reducing dependencies.

Azobenzene answered 5/10, 2011 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.