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:
- Make sure each header can be included on its own.
- 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
Boost Zip_Iterator and Std::Sort
Function-To-Function-Pointer "Decay"
Best Introduction to C++ Template Metaprogramming
Std::Thread Calling Method of Class
Compiling Qt 4.8.X for Visual Studio 2012
C++11 Way to Index Tuple at Runtime Without Using Switch
Configuring the Gcc Compiler Switches in Qt, Qtcreator, and Qmake
How Do Take a Screenshot Correctly with Xlib
Stl Rope - When and Where to Use
Get Current Time in Milliseconds Using C++ and Boost
In C++ What Causes an Assignment to Evaluate as True or False When Used in a Control Structure
C++ Overloading Array Operator
Std::Function and Std::Bind: What Are They, and When Should They Be Used
How to Implement a BéZier Curve in C++
What Is a Scalar Object in C++
Constexpr Const VS Constexpr Variables
How to Clear the Console in Both Windows and Linux Using C++