Cyclic dependency between two classes that try to include each other

Hello!
I am trying to implement a program in such a way that it uses a State Pattern (Here's the link that shows implementation in c++, just make sure you look at 29 points since the post uses OO approach.

Basically I have two classes at play: Zumo and Abstract State.
Zumo includes AbstractState so a variable can point to a child of that class.
AbstractState includes Zumo so it can create a variable to point at it.
I decided to use reference type of variable rather than a pointer since I am not manipulating with objects per sey.
If my memory is correct, when I passed Zumo to the AbstractState class before making zumo include AbstractState, the references (or the passing of them actually) worked as intended.

Here's the output of the error:

In file included from /home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:7:0,
                 from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h: In constructor 'AbstractState::AbstractState(String, Zumo&)':
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:11:85: error: invalid use of incomplete type 'class Zumo'
     AbstractState(String name, Zumo& z) : _zumo(z), _stateName(name),  _motors(_zumo.getMotors()), _ussensor(_zumo.getUltraSonicSensor()), _rfsensor(_zumo.getReflectanceSensor()) {}
                                                                                     ^
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:6:7: error: forward declaration of 'class Zumo'
 class Zumo;
       ^
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:11:115: error: invalid use of incomplete type 'class Zumo'
     AbstractState(String name, Zumo& z) : _zumo(z), _stateName(name),  _motors(_zumo.getMotors()), _ussensor(_zumo.getUltraSonicSensor()), _rfsensor(_zumo.getReflectanceSensor()) {}
                                                                                                                   ^
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:6:7: error: forward declaration of 'class Zumo'
 class Zumo;
       ^
In file included from /home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:7:0,
                 from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:11:155: error: invalid use of incomplete type 'class Zumo'
     AbstractState(String name, Zumo& z) : _zumo(z), _stateName(name),  _motors(_zumo.getMotors()), _ussensor(_zumo.getUltraSonicSensor()), _rfsensor(_zumo.getReflectanceSensor()) {}
                                                                                                                                                           ^
In file included from /home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:7:0,
                 from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:6:7: error: forward declaration of 'class Zumo'
 class Zumo;
       ^
In file included from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:0:
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h: In constructor 'Zumo::Zumo()':
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:126: error: type 'ManualState' is not a direct base of 'Zumo'
     Zumo() : _motors(), _ussensor(), _rfsensor(), _current_state("abstractstate", this), _prev_state("abstractstate", this), ManualState manual_state(this) {Serial.begin(9600);}
                                                                                                                              ^
In file included from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:0:
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:138: error: expected '(' before 'manual_state'
     Zumo() : _motors(), _ussensor(), _rfsensor(), _current_state("abstractstate", this), _prev_state("abstractstate", this), ManualState manual_state(this) {Serial.begin(9600);}
                                                                                                                                          ^
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:138: error: no matching function for call to 'AbstractState::AbstractState(const char [14], Zumo*)'
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:138: note: candidates are:
In file included from /home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:7:0,
                 from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:11:5: note: AbstractState::AbstractState(String, Zumo&)
     AbstractState(String name, Zumo& z) : _zumo(z), _stateName(name),  _motors(_zumo.getMotors()), _ussensor(_zumo.getUltraSonicSensor()), _rfsensor(_zumo.getReflectanceSensor()) {}
     ^
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:11:5: note:   no known conversion for argument 2 from 'Zumo*' to 'Zumo&'
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:8:7: note: AbstractState::AbstractState(const AbstractState&)
 class AbstractState
       ^
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:8:7: note:   candidate expects 1 argument, 2 provided
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:8:7: note: AbstractState::AbstractState(AbstractState&&)
/home/pavel/ZumoArduino/libraries/AbstractState/AbstractState.h:8:7: note:   candidate expects 1 argument, 2 provided
In file included from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:0:
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:138: error: no matching function for call to 'AbstractState::AbstractState(const char [14], Zumo*)'
     Zumo() : _motors(), _ussensor(), _rfsensor(), _current_state("abstractstate", this), _prev_state("abstractstate", this), ManualState manual_state(this) {Serial.begin(9600);}
                                                                                                                                          ^
...
/home/pavel/ZumoArduino/libraries/ManualState/ManualState.h:8:5: note:   candidate expects 1 argument, 0 provided
/home/pavel/ZumoArduino/libraries/ManualState/ManualState.h:6:7: note: ManualState::ManualState(const ManualState&)
 class ManualState : public AbstractState {
       ^
/home/pavel/ZumoArduino/libraries/ManualState/ManualState.h:6:7: note:   candidate expects 1 argument, 0 provided
/home/pavel/ZumoArduino/libraries/ManualState/ManualState.h:6:7: note: ManualState::ManualState(ManualState&&)
/home/pavel/ZumoArduino/libraries/ManualState/ManualState.h:6:7: note:   candidate expects 1 argument, 0 provided
In file included from /home/pavel/ZumoArduino/test-stateinheritance/test-stateinheritance.ino:1:0:
/home/pavel/ZumoArduino/libraries/Zumo/Zumo.h:16:138: error: expected '{' before 'manual_state'
     Zumo() : _motors(), _ussensor(), _rfsensor(), _current_state("abstractstate", this), _prev_state("abstractstate", this), ManualState manual_state(this) {Serial.begin(9600);}
                                                                                                                                          ^
exit status 1
Error compiling for board Arduino/Genuino Uno.

That's what AbstractState.h looks like:

#ifndef AbstractState_h
#define AbstractState_h
#include "Arduino.h"
#include "Zumo.h"

class Zumo;

class AbstractState
{
public:
    AbstractState(String name, Zumo& z) : _zumo(z), _stateName(name),  _motors(_zumo.getMotors()), _ussensor(_zumo.getUltraSonicSensor()), _rfsensor(_zumo.getReflectanceSensor()) {}
    String getName();

That's how Zumo.h looks like:

#ifndef Zumo_h
#define Zumo_h
#include "Arduino.h"
#include "Motors.h"
#include "UltraSonicSensor.h"
#include "ReflectanceSensor.h"
#include "AbstractState.h"
#include "ManualState.h"

class AbstractState;
//class ManualState;

class Zumo
{
public:
    Zumo() : _motors(), _ussensor(), _rfsensor(), _current_state("abstractstate", this), _prev_state("abstractstate", this), ManualState manual_state(this) {Serial.begin(9600);}

Basically, is there something I am doing wrong in terms of managing cyclic dependency, or the compiler is doing something wrong here?

I included relevant files. Also I included manualstate class that derives from abstract, but I don't think it shows any issues.

AbstractState.h (501 Bytes)

AbstractState.cpp (380 Bytes)

Zumo.h (984 Bytes)

Zumo.cpp (913 Bytes)

ManualState.cpp (826 Bytes)

ManualState.h (233 Bytes)

test-stateinheritance.ino (642 Bytes)

Having just got back from the pub, I thought I'd have a look at your code...

... I gave up, there's loads of errors and typo's in lots of places. It's a bit of a mess.

If you are trying something a bit tricky - start off simple, real simple and build up from there.

This is real simple and compiles ok...

// example for Arduino forum...
//  TonyWilk

class Zumo;

class AbstractState
{
public:  
  AbstractState( Zumo & z )   // AbstractState constructor
  : _zumo(z) 
  {
  };

  Zumo & get_zumo()           // return reference to Zumo
  { 
    return _zumo;
  };
  
  int get_zumo_something();   // get thing from our Zumo
  
protected:
  Zumo & _zumo;               // reference to our Zumo
  
};

class Zumo
{
public:  
  Zumo()                      // Zumo constructor;
  {
    something= 42;
  };
  
  Zumo( Zumo & z )            // Zumo copy constructor, the AbstractState constructor needs this
  {
    something= z.something;
  };
  
  int get_something()         // return this Zumo's protected something
  {
    return something;
  }
protected:
  int something;
};


AbstractState::get_zumo_something()
{
  return _zumo.get_something();
}

void setup() {
  Zumo a_zumo;
  AbstractState _an_AbstractState( a_zumo );
  int i, j;

  i= _an_AbstractState.get_zumo().get_something();

  j= _an_AbstractState.get_zumo_something();

}

void loop() {
  // put your main code here, to run repeatedly:

}

Add your 'complications' one at a time and make sure it compiles and does what you want before adding the next bit.

When you have something working, save it and then save it again as "MyThing-V27" or whatever, so if it stops working you can go back to the earlier one, or at least compare the two.

Hope that makes some sense... I have had a few beers :slight_smile:

Yours,
TonyWilk

P.S. Referring to my example, notice that any method of AbstractState which calls any method of Zumo must be defined later (usually in the .cpp file) - e.g. AbstractState::get_zumo_something()

Hello TonyWilk!!!
Really appreaciate the effort that you put into the example! (especially thinking while drunk, what a dedication lol)
But unfortunately, I am giving up on classes. While I was trying to fix the issue, I realised that I could use a proxy to connect to outside 'context', thus I created a class called context that would set selected state and the 'main' script would use it to set up a pointer to a particular state. However, I wanted to use Serial object and I discovered it doesn't work properly within a class. I am going to try to ask the post, but I don't know whether I will get a good response.
Thank you anyway!!!