0

Basically, I have two classes under two different header files. ToolBar and NewMenu (I will use the actual class names for my better understanding) Both of these classes are under namespace map. Now I have the class NewMenu declared inside of the class ToolBar. However, I have a member function in NewMenu, (HandleEvents(..., ToolBar& toolBar)), that handles events, but has the class ToolBar as a parameter in order to pass and edit certain information based on the event that happens. However, this seems to cause circular-dependency.

So basically... I started like this...

// ToolBar.h
#include "NewMenu.h"

namespace map
{
class ToolBar
{
private:
    NewMenu myNewMenu;

public:
    /* ... */
}
} // namespace map

//////////////////////////

// NewMenu.h
#include "ToolBar.h"

namespace map
{
class NewMenu
{
private:
    /* ... */

public:
    void HandleEvents(ToolBar& toolBar)
    {
        /* ... */
        //Use ToolBar function
        toolBar.tileMap.Create();

        /* ... */
    }
    /* ... */
}
} // namespace map

However, this causes circular-dependency. So I then did some research trying to solve this and got something like this...

// ToolBar.h
#include "NewMenu.h"

namespace map
{
class ToolBar
{
private:
    NewMenu myNewMenu;

public:
    /* ... */
}
} // namespace map

//////////////////////////

// NewMenu.h
//#include "ToolBar.h" 

namespace map
{
class ToolBar; //(I presume) to make a temporary reference to class ToolBar.
class NewMenu
{
private:
    /* ... */

public:
    void HandleEvents(ToolBar& toolBar)
    {
        /* ... */
        //Use ToolBar function
        toolBar.tileMap.Create(); //Error: incomplete type is not allowed

        /* ... */
    }
    /* ... */
}
} // namespace map

I'm not 100% sure, but based off of what I gathered, this should basically fix it(?), however, now I get an error in the HandleEvents() function saying "Error: incomplete type is not allowed." So my question is, what am I getting wrong and how do I fix this circular dependency?

(side note: I got some of my research here. Though sometimes I just need things shown a slightly different way to understand)

Thank you for your time and help.

Community
  • 1
  • 1
Uulamock
  • 330
  • 1
  • 3
  • 15

1 Answers1

3

The main problem is that you can't have a circular dependancy if a forward declaration is not enough to solve it. Since you are not just declaring handleEvents but even implementing it then the compiler must know the size of ToolBar. If you move the implementation in a cpp file then the problem disappear.

If the definition of B needs to know the size of A and the definition of B need to know the size of A then you are out of luck.

The best solution for your problem, since ToolBar contains a NewMenu is to solve it in a way similar to the following:

// ToolBar.h
#include "NewMenu.h" // needed because you need to know the size of NewMenu
class ToolBar {
  NewMenu menu;
  ..
}

// NewMenu.h
class ToolBar;

class NewMenu {
  void HandleEvents(const ToolBar& toolBar); // <- look, it's a reference, no need to know the size of ToolBar
}

// NewMenu.cpp
#include "NewMenu.h"
#include "ToolBar.h" // you can safely include it here
NewMenu::handleEvent(const ToolBar& toolBar) {
  toolBar.whatever();
}

In this way the problem is solved because NewMenu.h doesn't need to know the size of ToolBar, a forward declaration is enough, so there is no cross-include.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • It actually doesn't matter that it's a reference, incomplete types are allowed as parameters of function declarations (but not definitions). Moving the function body outside the class, after the definitions of all needed types, is the important thing. – Ben Voigt Jul 11 '14 at 23:37
  • This helps a ton more. I completely forgot to consider the .cpp file entirely! Thank you! It works perfectly fine now that I include `ToolBar.h` in the NewMenu.cpp. – Uulamock Jul 11 '14 at 23:49