Search code examples
c++circular-dependencyforward-declaration

Why am I suffering Circular Dependency here?


Utilities.h

#ifndef _UTILITIES_
#define _UTILITIES_

#include "MyFirstCairoPlugin.h"

class PLUG_CLASS_NAME;

class Utilities
{
private:
    PLUG_CLASS_NAME *pPlug;

public:
    Utilities(PLUG_CLASS_NAME *plug);
    ~Utilities();
};

#endif // !_UTILITIES_

Utilities.cpp

#include "Utilities.h"

Utilities::Utilities(PLUG_CLASS_NAME *plug) : pPlug(plug) {
    IColor color = IColor(100, 100, 100, 255);
}
Utilities::~Utilities() {

}

And this is where I've trouble, using this classe from MyFirstCairoPlugin.h:

#ifndef _MYFIRSTCAIROPLUGIN_
#define _MYFIRSTCAIROPLUGIN_

#include "IPlug_include_in_plug_hdr.h"
#include "resource.h"

#include "Utilities.h"

//class Utilities;

class MyFirstCairoPlugin : public IPlug
{
private:

public:
    Utilities *pUtilities;

    MyFirstCairoPlugin(IPlugInstanceInfo instanceInfo);
    ~MyFirstCairoPlugin();
};

#endif // !_MYFIRSTCAIROPLUGIN_

If I don't de-comment //class Utilities; (forward declaration), it is not able to use Utilities (even if I've included it above, with #include "Utilities.h"). It gives to me the "typical" Circular Dependency error `:

syntax error: missing ';' before '*' (compiling source file ..\..\..\IPlug_AddOns\Utilities.cpp)

Where am I wrong?


Solution

  • Utilities.h includes MyFirstCairoPlugin.h, MyFirstCairoPlugin.h includes Utilities.h, that is a circle, logically resulting in circle dependency.

    Here is what you should do instead:

    If a class needs another class right in the declaration, or if it is clearly a most essential part of it, include it. Example: A class "Image" might include a class "Color" If a class uses another class somewhat, like storing it in a pointer or using it in the call of some method, use forward declaration. If it doesn't need the other class at all, then well, it doesn't do either. For the second case, the implementation file would then include the dependent class.

    In your case, MyFirstCairoPlugin stores a pointer to Utilities, so it should do a forward declaration of Utilities, but not include it. By the way, that pointer should not be public.

    Here how it should look like:

    #ifndef _MYFIRSTCAIROPLUGIN_
    #define _MYFIRSTCAIROPLUGIN_
    
    #include "IPlug_include_in_plug_hdr.h" //<--- no idea what that is about
    #include "resource.h"
    
    class Utilities;
    
    class MyFirstCairoPlugin : public IPlug
    {
    private:
    
    public:
        Utilities* pUtilities; //<-- shouldn't be public, you should always use encapsulation 
    ...
    

    Utilities on the other hand does not even use MyFirstCairoPlugin, so we have our third case here. Why did you made it include MyFirstCairoPlugin in the first place? If that macro might be MyFirstCairoPlugin, then no problem, it already has a forward declaration. Wouldn't do that over a macro, though. Rather go with Utilities being a template class. By the way, "Utilities" is a quite broad name, sounds like it could easily lead to name collisions.

    Could look like this:

    #ifndef _UTILITIES_
    #define _UTILITIES_
    
    template<class T>
    class Utilities
    {
    private:
        T* pPlug;
    
    public:
        Utilities(T* plug);
    ...
    

    edit: seems you seem to be unhappy with templates, here is another possibility:

    Create an abstract class (/an interface) of which MyFirstCairoPlugin will be a subclass, providing all the methods that are needed within the implementation of Utilities. Let's say it's called "Plugin". It seems that you have some class like this already, but since I have no idea what IPlug is, I go with another name.

    Build Utilities around Plugin instead of MyFirstCairoPlugin or PLUG_CLASS_NAME. Then simply feed it an instance of MyFirstCairoPlugin, which is then a valid instance of Plugin. As long as the methods of Plugin are abstract and virtual, calling methods on the pointer to Plugin will call the methods of MyFirstCairoPlugin and everyone is happy.