0

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?

markzzz
  • 47,390
  • 120
  • 299
  • 507
  • 1
    Why does `utilities.h` need to `#include "MyFirstCairoPlugin.h"`? – Daniel Jour Dec 06 '16 at 09:10
  • Because `PLUG_CLASS_NAME` it's a macro, and "define" the name of the class `MyFirstCairoPlugin`, which is inside `MyFirstCairoPlugin.h` – markzzz Dec 06 '16 at 09:11
  • `MyFirstCairoPlugin.h` need not include `utilities.h` if you forward declare `Utilities`. – Arunmu Dec 06 '16 at 09:11
  • @Arunmu: but this should be the same with opposite. If I include `Utilities.h`, why I should forward declare Utilities? – markzzz Dec 06 '16 at 09:12
  • 2
    You have eliminated the circular dependency between the classes, but you still have a circular dependency between the headers. – molbdnilo Dec 06 '16 at 09:12
  • 1
    @paizza Because of what molbdnilo said in above comment. Thats how you break dependency. – Arunmu Dec 06 '16 at 09:14
  • Remember that `#include "foo"` literally means "insert the contents of file 'foo' here"; it's a very simple (and stupid) mechanism from the 1960s. It's nothing like the higher-level concept "make the definitions in module 'foo' available" like in more modern languages. – molbdnilo Dec 06 '16 at 09:21
  • That's crazy! So if I want to use `MyFirstCairoPlugin` (which is inside `MyFirstCairoPlugin.h`) I need to include the whole content of `MyFirstCairoPlugin.h` for every compilation unit? Damn it's lots of "copy & paste", and the code is huge for a simple class definition :O – markzzz Dec 06 '16 at 09:39
  • hi,you can try adding #pragma once in all header file,preferably on top – Lokanath Dec 06 '16 at 10:40

2 Answers2

1

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.

Aziuth
  • 3,652
  • 3
  • 18
  • 36
  • I include `MyFirstCairoPlugin` inside Utilities because PLUG_CLASS_NAME it's a macro that "define" the name of the class MyFirstCairoPlugin, which is inside MyFirstCairoPlugin.h. – markzzz Dec 06 '16 at 09:52
  • @paizza That sounds like a really strange construct of dependencies. Don't do that. If I saw your classes without knowing, I had no idea where you defined that macro. Would have never guessed that the class that uses it does that. Unnecessarily increases coupling. Done an edit about my post, use the template solution. – Aziuth Dec 06 '16 at 09:58
  • I'll go it a try, but I've some trouble splitting .h and .cpp with the template http://stackoverflow.com/questions/40993286/whats-wrong-with-this-use-of-template – markzzz Dec 06 '16 at 10:38
  • if you work with header and cpp files, this solution is terrible to manage :( – markzzz Dec 06 '16 at 11:05
  • Huh? You have to do nothing more than adding a single line of template parameters per method in the cpp file. Pretty much common, easily readable. Don't see the problem. If you want to be able to switch your plug class all the time, a template is what you want. That said, another thing you could do is to create an abstract class "Plugin", build Utilities around that class (especially since you use pointers anyway) and then make MyFirstCairoPlugin to be a subclass of Plugin. As it actually seems to be right now. Depends on your implementation if that is viable. – Aziuth Dec 06 '16 at 11:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/129900/discussion-between-paizza-and-aziuth). – markzzz Dec 06 '16 at 11:42
0

Look how it's included step by step:

  • in Utilities.cpp, you include Utilities.h
  • now you #define _UTILITIES_
  • then you do include MyFirstCairoPlugin.h
  • in there you include Utilities.h again
    • but because of #ifndef _UTILITIES_, the class definition is not included - _UTILITIES_ is already defined (see second step)!

So class Utilities is not defined yet, and you need forward declaration.

R Risack
  • 69
  • 8