Avoiding Circular Dependencies of header files

C++Software DesignArchitecture

C++ Problem Overview


Do you have any good advice on how to avoid circular dependencies of header files, please?

Of course, from the beginning, I try to design the project as transparent as possible. However, as more and more features and classes are added, and the project gets less transparent, circular dependencies start happening.

Are there any general, verified, and working rules? Thanks.

C++ Solutions


Solution 1 - C++

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!

Solution 2 - C++

  • Use forward declarations where possible.
  • Move any header includes out of a header file and into the corresponding cpp file if they are only needed by the cpp file. Easiest way to enforce this is to make the #include "myclass.h" the first include in myclass.cpp.
  • Introducing interfaces at the point of interaction between separate classes can help reduce dependencies.

Solution 3 - C++

Some best practices I follow to avoid circular dependencies are,

  1. Stick to OOAD principles. Don't include a header file, unless the class included is in composition relationship with the current class. Use forward declaration instead.
  2. Design abstract classes to act as interfaces for two classes. Make the interaction of the classes through that interface.

Solution 4 - C++

A general approach is to factor out the commonalities into a third header file which is then referenced by the two original header files.

See also Circular Dependency Best Practice

Solution 5 - C++

depending on your preprocessor capabilities:

#pragma once

or

#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif

If you find it very boring to design header files maybe makeheaders from Hwaci (designers of SQLite and fossil DVCS) could be of interest for you.

Solution 6 - C++

What you're aiming at is a layered approach. You can define layers where modules can depend on lower layer modules but the inverse should be done with observers. Now you can still define how fine-grained your layers should be and whether you accept circular dependency within layers, but in this case I would use this.

Solution 7 - C++

In general header files should forwardly declare rather than include other headers wherever possible.

Also ensure you stick to one class per header.

Then you almost certainly will not go wrong.

The worst coupling usually comes from bloated template code. Because you have to include the definition inside the header, it often leads to all kinds headers having to be included, and then the class that uses the template includes the template header, including a load of other stuff.

For this reason, I would generally say: be careful with templates! Ideally a template should not have to include anything in its implementation code.

Solution 8 - C++

Altough Artyom provided best answer this tutorial is also great and provides some extenstions http://www.cplusplus.com/forum/articles/10627/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBunkai.SatoriView Question on Stackoverflow
Solution 1 - C++ArtyomView Answer on Stackoverflow
Solution 2 - C++jon-hansonView Answer on Stackoverflow
Solution 3 - C++SullaView Answer on Stackoverflow
Solution 4 - C++Ed GuinessView Answer on Stackoverflow
Solution 5 - C++BenoitView Answer on Stackoverflow
Solution 6 - C++stefaanvView Answer on Stackoverflow
Solution 7 - C++CashCowView Answer on Stackoverflow
Solution 8 - C++rank1View Answer on Stackoverflow