C++ Circular Dependency in Header Files

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:

  1. Make sure each header can be included on its own.
  2. 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 #includes from the header files themselves.



Related Topics



Leave a reply



Submit