-1

I am having quite the issue with forward declarations. I have a class, SharedContext.h that has, among other things, a pointer to another class StateMachine.h. StateMachine also has a pointer to the SharedContext. This would be easy enough if that was all. I have other classes like this already. I would just need to:

#include "StateMachine.h" in my SharedContext.h file, and forward declare the SharedContext in the StateMachine.h file, then #include "SharedContext.h" in the StateMachine.cpp file.

This breaks down however, when I need to include more classes into StateMachine. I have a State_Base.h, and a State_DIYACMenu.h and State_DIYACMenu.cpp. State_Base.h also has a pointer to SharedContext, and needs to include it. State_DIYACMenu.h obviously includes State_Base.h, and then finally my StateMachine includes the State_DIYACMenu. So there is the circular dependency.

I thought I would then be able to solve this by using a forward declaration of SharedContext in State_Base.h, then using #include "SharedContext.h" in the State_DIYACMenu.cpp and StateMachine.cpp. But I am still getting a "Member access into incomplete type StateMachine" error in the StateMachine class.

Link to the github project: https://github.com/djpeach/DIY-Arcade-Cabinet/tree/master/menu/menu

  • Seems confusing with no minimal class examples or file examples. One thing I suggest would be to make sure you also have header guards. Either #pragma once or #ifndef SOMETHING_H #define SOMETHING_H #endif – Omid CompSCI Aug 07 '19 at 03:11
  • yes I am using #pragma once in all header files. I triple checked this. And its more than a bit of code, so I will add a link to github. one moment – Daniel Peach Aug 07 '19 at 03:13
  • 1
    I recommend placing the code, in [mcve] form, in the question rather than linking to it. Links rot and when this one goes, the question becomes pretty much useless. – user4581301 Aug 07 '19 at 03:27
  • ok, i'll get that written up. in the meantime, have any ideas? – Daniel Peach Aug 07 '19 at 03:33

1 Answers1

0

I suggest a walk around and avoid using forward declarations.

Forward declarations are a nice method to resolve circular dependency when you write simple enough code but when your code grows in complexity it becomes harder and harder to code without getting into a circular dependency issue due to various restrictions it implies.

To get around it - use interface classes.

class My_Interface_Of_StateMachine
{
public:
    virtual ~My_Interface_Of_StateMachine() = default;
    virtual void foo() = 0;
// declarations of all functions you use
};
// put it into a header My_Interface_Of_StateMachine.h

Let your SharedContext have only pointer towards an My_Interface_Of_StateMachine and make your StateMachine inherit from the interface class My_Interface_Of_StateMachine.

class StateMachine:
    public My_Interface_Of_StateMachine
{
public:
    void foo() override;
//implementation of all the functions
};

This way you have no circular dependency.

If for some reason you find that using virtual methods is too slow then you can cast the interface class into the real class via dynamic casting in the cpp file.

ALX23z
  • 4,456
  • 1
  • 11
  • 18