Double include solution? - c++

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.

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?

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;).

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

Related

Avoid forward redeclaration. Is it a good practice? Is it necessary?

I am used to do forward declarations of classes like this:
// file 1
#ifndef A_HPP
#define A_HPP
class A
{
...
};
#endif
// file 2
#ifndef B_HPP
#define B_HPP
#ifndef A_HPP
class A;
#endif
class B
{
};
#endif
As you can see in file 2, I try to safe the forward declaration of A. So, it should not be possible to redeclare A.
I have seen a lot of code where they don't put the guards around the forward declarations.
I wanted to know if what I am doing is really necessary or if it adds some kind of safety. Would any of these approaches benefit compilation times more than the other? Which one would you use? Why?
You are NOT adding any safety. Declarations in C++ can be repeated any times you want, as long as they are all coherent.
Furthermore, this is not a good practice. I've never seen someone doing like that. Think what would happen if you move A's definition from a.hpp: you should change all the scope guards around A's forward declaration in all files. Life is already complicated enough.
You dont need to use the marco guard as compiler will know how to process both file.
No need to out the follow 3 lines in file2.h
#ifndef A_HPP
class A;
#endif
use the following line is already good enough
#include "file1.h"
The concept of forward declaration
forward declaration is used to notify compiler there is a class ( or struct or whatever type you want ) named as "A" when reading the file. but compiler knows the declaration is not specific here, but may be in the other file.
At that time, compiler will know:
1) OK, there is a class named as "A", I will remember it.
2) I dont know its size and detail. But if coder use only the A* (pointer of A), it is OK and I dont need to know the detail of A.
Forward declaration is useful. Especially classes are interrelated.
But, if the type name of A is not in sync between both files. g++ will fail to compile.
Compilation time
Forward declaration is also good to use as it save the compilation time.
If the file does not change, g++ will not re-compile again.
While the file 2 use only the forward declaration, so no matter how you change the file 1 or class A, file 2 will not be compile again.

Error C2504 - Base class undefined

I have a rather simple problem
This is my firstcluster.h
#pragma once
#include "cluster.h"
class FirstCluster:public Cluster{
...
public:
...
};
Code for cluster.h:
#pragma once
// File: cluster.h
class Cluster {
protected:
...
public:
...
};
And i'm getting the error:
error C2504: 'Cluster' : base class undefined
Sometimes i get this IntelliSense error:
IntelliSense: incomplete type is not allowed ... Line 10 Column 27
But it doesn't always come up.
The cluster.h is included, as you can see, and all other header files are protected with #pragma once
I really don't know what could go wrong here?
Can circular include make problems even if i protected everything with #pragma once?
I'm using Visual Studio 2010.
I got this due to circular include.
I included all my headers in "include.h" and include it in everywhere else.
I managed to avoid circular include by just including standard headers in include.h.
I've had the exact same problem, adding
#ifndef CLUSTER_H
#define CLUSTER_H
/* your code */
#endif
helped to solve the problem. the ifndef part is obviously for include duplications but "define", i think, did help.
This code looks normal, so:
if cluster.h actually defines Cluster class, then check for missing namespace around Cluster (if you use a namespace), upper-lower case usage in 'Cluster' vs 'cluster', 'cLuster', etc., also check that the Cluster definition is not local to another class.
Hope this helps.
This error occurs due to circular include so We can handle this by adding the header of child class in the bottom of the parent class

"Does not name a type" error, but class pointer already has forward declaration?

I am getting this compiler error
error: 'RawLog' does not name a type
Here is the relevant code:
//DataAudit.h
#ifndef DATAAUDIT_H
#define DATAAUDIT_H
class RawLog;
class DataAudit
{
...
private:
RawLog* _createNewRawLog(); // This is the line indicated with the error
};
#endif // DATAAUDIT_H
Usually a forward declaration resolves this kind of error. This answer indicates that a circular header inclusion may cause this. But doesn't the use of the #ifndef and #define statements prevent circular header inclusion?
Is there another reason I might see this error?
What are some avenues of approach I could use to further deduce the nature of this error?
Update: This is rather odd. I have a Globals.h file, and if I define a new enum in Globals.h, the error appears. Then if I comment out the enum, the error goes away. This leads me to think that the circular dependency has existed for a while, and adding the enum somehow re-orders the compilation units, thus exposing the dependency that wasn't there before?
The #ifndef header guard doesn't prevent circular dependencies. It just prevents multiple inclusions of the same header in a single file.
Looks like a circular dependency to me. This means you #include a header in DataAudit.h that #includes DataAudit.h either directly or indirectly.
In the end, I am not sure I understand completely why the error occurred, but this is what I did to resolve it, and some other related information. Maybe this will help others that come across this question.
For each header file in my project
For each #include "..." in the header
If there are no references to the class in the #include, remove it.
If there are only pointers to the class defined in the #include, then replace it with a class ... forward declaration.
If there is a member instance of the class defined in #include and it makes sense to use a pointer and allocate the member on the heap, then change the member to a pointer, and replace the #include with a class .... forward declaration.
Go through my Globals.h and move anything that can be moved out of it to more localized and specific header files.
Specifically, remove an enum that was defined is Globals.h, and place it in a more localized header file.
After doing all this I was able to make the error go away. Strangely enough, the enum in Globals.h seemed to be a catalyst for the error. Whenever I removed it from Globals.h, the error would go away. I don't see how this enum could cause the error, so I think it indirectly led to the error somehow. I still wasn't able to figure out exactly how or why, but it has helped me for this guideline when coding in C++:
Don't put anything in a header file unless it needs to be there. Don't
place anything in a Globals.h that can be placed in a more localized
file. Basically, do all you can to reduce the amount of code that is
included through the #include directives.

Is it possible to forward declare a typedef that is within a namespace?

I've looked around and I can't quite tell if the other similar questions answer this or not.
// lib.h
namespace lib_namespace
{
struct lib_struct
{
typedef std::vector<LibObject> struct_value;
};
typedef lib_struct::struct_value lib_value; // compiler points here
};
// my.h
// attempt at forward declaration
namespace lib_namespace { class lib_value; };
...
// my.cpp
#include "lib.h"
I get a redefinition compiler error which is understandable, but is there a way to forward declare that typedef?
My intent is to avoid adding lib.h as a dependency outside of the library I'm making. Perhaps there's a better way to achieve that?
Edit: To clarify, I'm trying to avoid adding an additional include directories line to all the project files that would use the library I'm creating because of the third party library I'm using and the above situation is where I'm stuck. So it's OK if I include lib.h in my.cpp, but not my.h.
You compiler complains, because lib.h and my.h are independent header files and they don't know about each other. Moreover, unlike the actual class, the typedef doesn't support the forward declaration.
Suppose, you don't want to #include"lib.h", then you can create a separate header which has typedef lib_struct::struct_value lib_value; and the relevant part related to it. #include that new header wherever needed.
Namespaces are not relevant to the question. You cannot forward declare a typedef; only actual types (classes and structs) can be forward declared.

C++ Agent : Base class undefined error in Game

I have 6 C++ header files. There are a lot of includes so I tried to make it so that I use as little as I can. But I keep getting an error from the very beginning saying that a class "Agent" is undefined. I defined it and included it and can't find the problem here are the 2 header files that are causing the problem:
Sinbad.h:
#ifndef SINBAD_H
#define SINBAD_H
#pragma once
#include "Agent.h"
#define NUM_ANIMS 13 // number of animations the character has. Should be made character specific
class Agent;
class Sinbad : public Agent {
Agent.h:
#ifndef AGENT_H
#define AGENT_H
#include <deque>
#include "aStar.h"
extern Ogre::SceneManager* sceneMgr; // Defined in main.cpp
class GridNode; // forward declarations
class Grid;
class Astar;
class Agent {
Here's the error I am getting:
1>c\gameengine_solution\sinbad.h(12) : error C2504: 'Agent' : base class undefined
It looks like something is referring to class Agent before it is defined, i.e. probably in aStar.h.
EDIT: Search for #define AGENT_H everywhere in your source. If you find it anywhere outside Agent.h, that means the Agent class might never be defined, if only because Agent.h can be #included with AGENT_H already #defined.
Do not redeclare class Agent in Sinbad.h. You already included Agent.h. Seems also to be the case in Agent.h with Grid and Astar.
Some of the comments suggest you're unsure how forward declaring works.
Forward declare a type when you need to tell the compiler that the type exists, but do not need any of its definition. Generally, this is done in a header when a class's members or methods only have pointers or references to the type. In order to do anything that involves dereferencing the pointer or using the reference, you will need to include the header that defines the type, usually in the source that defines the methods of the class.