Recursive use of classes eachother on multiple files

Hi guys,

I'm not familiar with this form of programming so I need your advice.

I have several modules like below and I want one to have access to each other's class instance, what is the best approach to include recursive or recursive class declaration?

I can successfully use this approach with multiple classes, also from multiple files, but no one can access cfg.hpp

Additional information (later):

A) I'm trying to do a modular configuration, where the configuration needs to read the module values ​​(in this case it needs to send to syslog as well), yet the module values ​​need to read the configuration values ​​(in this case syslog ip, syslog priority )

B) I have no issues with duplicate instances/includes, everything works fine, no warnings or errors when compiling and linking.

C) When I put the separate code into .cpp and .h, it remains the same (since I will have many modules, the single-header class looks better for me, but it's okay to separate the files)

D) Maybe using a class pointer to syslog.hpp can solve this problem, but I have no idea how to implement it as I'm new to C++

E) If you can provide some examples of how to solve this, I would greatly appreciate it.

1) main.cpp
1
2
3
4
5
6
7
8
9
10
  #include "cfg.hpp"
  #include "syslog.hpp"
  #include "another.hpp"

  int main(int argc, char** argv) {
    cfg.save();
    cfg.load();

    for (;;) {}
  }



2) cfg.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  #ifndef mycfg_h 
  #define mycfg_h
  
  #include "syslog.hpp"
  
  typedef std::vector<cfgCallbackLoad> listCallbackLoad; 
  typedef std::vector<cfgCallbackSave> listCallbackSave;

  class mycfg {
    private:
      listCallbackLoad  _onLoad;
      listCallbackSave  _onSave;
    	
    public:	
      char * url;
		
      mycfg() {}
			
      void onLoad( cfgCallbackLoad newEvent ) {
        _onLoad.push_back( newEvent );  
      }
    	
      void onSave( cfgCallbackSave newEvent ) {
        _onSave.push_back( newEvent );
      }
    	
      void load() {
        // load some pairs from json
    	  
        // call each callback
        for ( auto callback : _onLoad ) { callback( json ); }
    		
        if ( syslog.priority == 0 ) 
          syslog.log( "json file loaded!" );
      }
    	
      void save() {
        // add some pairs to json
    	  
        // call each callback
        for ( auto callback : _onSave ) { callback( json ); }
   
        syslog.log( "json file saved!" )
      }
  };
  
  mycfg cfg;   // global public instance, like extern
  
  #endif 


3) syslog.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  #ifndef mysyslog_h
  #define mysyslog_h
  
  #include "cfg.hpp"
  
  class mysyslog {
    private:
      int priority;
		  
      void OnCfgLoad( JsonDocument& json ) { // Event callbak 
        // do something with json
      }
			
      void OnCfgSave( JsonDocument& json ) { // Event callbak 
        // put something more into json
      }
    public:	
      mysyslog() {
        // attach to cfg events
        #ifdef mycfg_h
          cfg.onSave( std::bind(&mycfg::OnCfgSave, this, std::placeholders::_1 ) );
          cfg.onSave( std::bind(&mycfg::OnCfgSave, this, std::placeholders::_1 ) );
        #endif

         printf( cfg.url );
      }
			
      void log( char * msg ) {
        // log this message
      }
  };
  
  mysyslog syslog; // global public instance, like extern
  
  #endif   


4) another.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  #ifndef myanother_h
  #define myanother_h
  
  #include "cfg.hpp"
  #include "syslog.hpp"
  
  class myanother {
    private:
      void OnCfgLoad( JsonDocument& json ) { // Event callbak 
        // do something with json
      }
			
      void OnCfgSave( JsonDocument& json ) { // Event callbak 
        // put something more into json
      }
    public:	
      myanother() {
        // attach to cfg events
        #ifdef mycfg_h
          cfg.onSave( std::bind(&mycfg::OnCfgSave, this, std::placeholders::_1 ) );
          cfg.onSave( std::bind(&mycfg::OnCfgSave, this, std::placeholders::_1 ) );
        #endif
				
        syslog.log( "something..." );
      }
  };
  
  myanother another ; // global public instance, like extern
  
  #endif 
Last edited on
You can easily remove that circular dependencies when you put the functions (like load()/save()) that uses those objects into the .cpp and include the required header there.

global public instance, like extern
Actually you need to put these definitions into the .cpp as well and use extern. Otherwise you will get multiple definitions when the header is included more than once.
Last edited on
between forward declarations and pointers and inheritance, you can usually avoid the situation entirely. It does happen on occasion, but in my experience the situation is 95% of the time a design fubar or a band-aid applied later, not a necessary construct. The few times that it is necessary, you have additional tools to work around it.
Topic archived. No new replies allowed.