Circular dependency between C header files
The solution is to simply use some manner of program design. Each "object"/"module" in your program should consist of one h file and one c file. The h file is the public interface. Each such object should only be concerned with its own designated task. It should only include the resources needed to perform that task.
With such a design, there should never be any circular dependencies, or the design is flawed. You should not fix a bad design with various code tricks, you should re-do the design.
But of course the same resource could be included multiple time from different parts of the code. This is why we always use header guards in every single h file.
C++ Circular Dependency in Header Files
You could use this:
A.h
#include <B.h>
#ifndef A_H
#define A_H
class A
{
public:
B b1;
int m_a;
};
#endif // A_H
B.h
#ifndef B_H
#define B_H
class A;
class B
{
public:
int f(A &a);
};
#include <A.h>
inline int B::f(A &a)
{
return a.m_a;
}
#endif // B_H
main.cpp
#include <iostream>
#include <A.h> // these could be in any order
#include <B.h>
int main()
{
A a;
B b;
std::cout << "Calling b.f(a): " << b.f(a) << std::endl;
return 0;
}
Fixing circular dependencies c++17 headers
The usual fix is simple:
struct Xchart; // declares Xchart; definition is elsewhere.
short WINAPI MyFunction(Xchart *mychart); // Function declaration.
Only toolkit.cpp will need the definition of Xchart
, but .cpp files themselves are not included elsewhere and don't contribute to circular inclusions.
Circular dependency in single C header file. Forward declaration needed?
You can make the declaration of a struct
before its definition:
/* declaration */
struct foo;
.....
/* definition */
struct foo
{
....
};
Anywhere you write struct foo
is a declaration of the struct, so you don't have to put it in a separate line, you can have it in a typedef, pointer declaration, etc..
Just be aware that sometimes, like in variable declarations of type struct foo
you also need the definition (to calculate the variable size);
/* declare struct foo ..*/
struct foo;
/* .. or declare struct foo ..*/
typedef struct foo foo;
/* .. or declare struct foo ..*/
struct foo *p;
/* .. or declare struct foo */
int bar (struct foo *p);
/* Not valid since we don't have definition yet */
struct foo f1;
/* definition */
struct foo
{
....
};
/* Valid */
struct foo f2;
In your case you haven't given the struct a name; you've just made a typedef
that is an alias for an anonymous struct. So to forward declare your struct you have to give it a name:
/*
forward declare the `struct stage_table_context_t` and give it a typedef alias
with the same name as the structs name
*/
typedef struct stage_table_context_t stage_table_context_t;
typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
struct stage_table_context_t{
uint32_t error_number;
stage_t* current_stage;
} stage_table_context_t;
Solving a circular dependency - C
It can be useful to define enums in their own file(s), and if you do that here, your problem will disappear.
Avoiding Circular Dependencies of header files
If you have circular dependency then you doing something wrong.
As for example:
foo.h
-----
class foo {
public:
bar b;
};
bar.h
-----
class bar {
public:
foo f;
};
Is illegal you probably want:
foo.h
-----
class bar; // forward declaration
class foo {
...
bar *b;
...
};
bar.h
-----
class foo; // forward declaration
class bar {
...
foo *f;
...
};
And this is ok.
General rules:
- Make sure each header can be included on its own.
- If you can use forward declarations use them!
Resolving a circular reference in c++ header files
Forward reference (or forward declaration).
In Deck.h
you don't need to #include "CardFactory.h"
, instead just declare the class.
class CardFactory;
This should work because in Deck
class you are only using pointer to class CardFactory
C circular dependency
Seems like you shouldn't need to include anything in any of the files. A forward declaration of the relevant types should be sufficient:
#ifndef MapTest_vertex_h
#define MapTest_vertex_h
struct edgelist;
typedef struct
{
char* name;
float x, y;
edgelist* edges; // C++ only - not C
} vertex;
#endif
etc. In C coding, you have to write:
struct edgelist;
typedef struct
{
char* name;
float x, y;
struct edgelist* edges;
} vertex;
How can I resolve this mutual dependency between header files?
I suppose you could argue that I'm addressing the software-design aspect here, but I don't know how to do this without slightly refactoring your code. Namely, by avoiding the typedef temporarily. (Although I would advise dumping the typedef's permanently.) For your particular case, table.h doesn't need to know what ObjectString is, since it only uses a pointer to it. So you can simply not import "object.h" in table.h, and instead write:
object.h:
#ifndef s_object_h
#define s_object_h
#include "common.h"
#include "table.h"
typedef enum {
OBJECT_STRING
} ObjectType;
typedef struct {
ObjectType type;
Table attributes;
} Object;
struct ObjectString {
Object base;
char* chars;
int length;
};
typedef struct ObjectString ObjectString;
bool stringsEqual(ObjectString* a, ObjectString* b);
#endif
table.h:
#ifndef s_table_h
#define s_table_h
#include "value.h"
typedef struct {
struct ObjectString* key;
Value value;
} Entry;
typedef struct {
int capacity;
int count;
Entry* entries;
} Table;
void initTable(Table* table);
void setTable(Table* table, struct ObjectString* key, Value value);
bool getTable(Table* table, struct ObjectString* key, Value* out);
#endif
C++ : Headers Including each others causes an Error class has not been declared
To break the circular dependency, you need to add a forward declaration of the depended-on classes to each of your header files, like this:
#ifndef A_H
#define A_H
#include <iostream>
class CRoom;
class CPlay {
...
and:
#ifndef D_H
#define D_H
#include <iostream>
class CPlay;
class CRoom {
...
Note that this allows you to remove the #include
s from the header files themselves.
Related Topics
Qsqldatabase: Qmysql Driver Not Loaded on Ubuntu 15.04 64Bits
Traceback a Pointer in C++ Code Gdb
Constraining the Existing Boost.Spirit Real_Parser (With a Policy)
Why Would I Std::Move an Std::Shared_Ptr
What Is a Good Random Number Generator for a Game
How to Compile C++ with C++11 Support in MAC Terminal
Get a Reverse Iterator from a Forward Iterator Without Knowing the Value Type
How Can Cstring Be Passed to Format String %S
Application Has Failed to Start Because Msvcp100D.Dll Was Not Found, Reinstalling App May Work
Cmake: Project Structure with Unit Tests
Abstract Class VS Interface in C++
Std::Pow Produce Different Result in 32 Bit and 64 Bit Application
Differencebetween Include_Directories and Target_Include_Directories in Cmake
How to Handle a Transitive Dependency Conflict Using Git Submodules and Cmake