Cyclic Dependency Between 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.

Cyclic dependency between header files

In the headers, forward declare the member functions:

class Node
{
Tree * tree_;
int id_;

public:
Node(Tree * tree, int id);
~Node();
void hi();
};

In a separate .cpp file that includes all the required headers, define them:

#include "Tree.h"
#include "Node.h"

Node::Node(Tree * tree, int id) : tree_(tree), id_(id)
{
tree_->incCnt();
}

Node::~Node()
{
tree_->decCnt();
}

etc

This also has the effect of keeping your headers readable, so it is easy to see a class's interface at a glance.

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;
}

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!

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

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.



Related Topics



Leave a reply



Submit