Search code examples
c++dependenciesincludesingletoncyclic-dependency

C++ cyclic dependency of classes (Singleton)


i have a problem to compile the classes with cyclic dependency, and i can not find the way to compile my code

the main problem is appeared in chain of classes that has dependency to each others

for example i have 6 header files(Classes) (A, B, C, D, E, F)

A included in E

F, D included in A

E included in F, D

now i have a loop and cant fix it

i simplify the problem then create the simple example to show what is my exact problem

A.h

#ifndef A_H
#define A_H
#include "B.h"

class A
{
public:
    static A& getInstance()
    {
        static A  instance; 
        return instance;
    }
    int i;
    int sum()
    {
        return i+B::getInstance().j;
    }
private:
    A() {}
};
#endif

B.h
#ifndef B_H
#define B_H
#include "A.h"

class B
{
public:
    static B& getInstance()
    {
        static B  instance; 
        return instance;
    }
    int j;
    int sum()
    {
        return j+A::getInstance().j;
    }
private:
    B() {}
};
#endif
main.cpp

#include "A.h"
#include "B.h"
#include <iostream>
int  main()
{

    A::getInstance().i=1;
    B::getInstance().j=2;
    int t1=A::getInstance().sum();
    int t2=B::getInstance().sum();
    std::cout<<t1<<std::endl;
    std::cout<<t2<<std::endl;
    return 0;
}


g++ main.cpp
In file included from A.h:3:0,
                 from main.cpp:1:
B.h: In member function ‘int B::sum()’:
B.h:17:12: error: ‘A’ has not been declared
   return j+A::getInstance().j;

is there any way or solutions to resolve this?


Solution

  • If you can't use .cpp files for some reason, you can do this:

    a.h:

    #pragma once
    
    class A {
    public:
        static A& getInstance();
        int i;
        int sum();
    
    private:
        A();
    };
    

    a_impl.h:

    #pragma once
    #include "a.h"
    #include "b.h"
    
    inline A& A::getInstance() {
        static A instance;
        return instance;
    }
    
    inline int A::sum() {
        return i + B::getInstance().j;
    }
    
    inline A::A() {
    }
    

    b.h:

    #pragma once
    
    class B {
    public:
        static B& getInstance();
        int j;
        int sum();
    
    private:
        B();
    };
    

    b_impl.h:

    #pragma once
    #include "a.h"
    #include "b.h"
    
    inline B& B::getInstance() {
        static B instance;
        return instance;
    }
    
    inline int B::sum() {
        return j + A::getInstance().i;
    }
    
    inline B::B() {
    }
    

    And then first include declarations a.h and b.h, and then implementations a_impl.h and b_impl.h:

    #include "a.h"
    #include "b.h"
    #include "a_impl.h"
    #include "b_impl.h"
    #include <iostream>
    
    int main() {
        A::getInstance().i = 1;
        B::getInstance().j = 2;
        int t1 = A::getInstance().sum();
        int t2 = B::getInstance().sum();
        std::cout << t1 << std::endl;
        std::cout << t2 << std::endl;
    }
    

    Now it will compile. In this particular example, B (or A) could've been implemented inside class definition (so, no b_impl.h). I separated declarations and definitions for both classes for the sake of symmetry.