1

I'm facing a problem using forward declaration, and I don't know how to fix it. Here's my files:

BubblePlug.h

#ifndef _BUBBLEPLUG_
#define _BUBBLEPLUG_

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

class IPianoRoll;
class IMidiEngine;

class BubblePlug: public IPlug
{
private:

public:
    IMidiEngine *pMidiEngine;
    IPianoRoll *pPianoRoll;

    BubblePlug(IPlugInstanceInfo instanceInfo);
    ~BubblePlug();
};

#endif // !_BUBBLEPLUG_ 

BubblePlug.cpp

#include "BubblePlug.h"
#include "IPlug_include_in_plug_src.h"
#include "IPianoRoll.h"
#include "IMidiEngine.h"

BubblePlug::BubblePlug(IPlugInstanceInfo instanceInfo) : IPLUG_CTOR(10, 1, instanceInfo) {
    pPianoRoll = new IPianoRoll(this, 8, 8);
    pMidiEngine = new IMidiEngine(this);
}
BubblePlug::~BubblePlug() { 
    delete pPianoRoll;
    delete pMidiEngine;
}

IPianoRoll.h

#ifndef _IPIANOROLL_
#define _IPIANOROLL_

#include "IMidiEngine.h"

class IPianoRoll : public IControl
{
private:
    BubblePlug *pBubblePlug;

public:

    IPianoRoll(BubblePlug *bubbleplug, int x, int y) : IControl(bubbleplug, IRECT(x, y, x + 10, y + 10)), pBubblePlug(bubbleplug) {

    }
    ~IPianoRoll() {

    };

    bool Draw(IGraphics *pGraphics) {
        return true;
    }

    void Random(bool onlyScore = false) {
        pBubblePlug->pMidiEngine->Init();
    }

    void Start() {

    }
};

#endif // !_IPIANOROLL_ 

IMidiEngine.h

#ifndef _IMIDIENGINE_
#define _IMIDIENGINE_

class IMidiEngine
{
private:
    BubblePlug *pBubblePlug;

public:
    IMidiEngine(BubblePlug *bubbleplug) : pBubblePlug(bubbleplug) {

    }
    ~IMidiEngine() {

    };

    void Init(bool randomScore = true) {
        pSamplwhk->pPianoRoll->Start();
    }
};

#endif // !_IMIDIENGINE_    

when I compile, it says around pSamplwhk->pPianoRoll->Start();:

use of undefined type 'IPianoRoll'
left of '->Start' must point to class/struct/union/generic type

VS2015 find each element writing the code (I've no problem), it happens only when I compile (Build).

Why? I pass BubblePlug and I do forward of both IPianoRoll and IMidiEngine, including them in order (on BubblePlug.cpp).

IMidiEngine should know everythings about IPianoRoll (which it is included first).

At least, I should have problem at "runtime", why at compile?

Can you help me to understand the problem and how to fix it? Thanks.

markzzz
  • 47,390
  • 120
  • 299
  • 507

1 Answers1

1

IPianoRoll.h includes IMidiEngine.h, so no matter in which order you include the two files, the definition of IPianoRoll will always come after the init function where it is being used.

One way to avoid this is to move the body of the init function into a separate .cpp file:

In IMidiEngine.h:

void Init(bool randomScore=true);

In IMidiEngine.cpp:

void IMidiEngine::Init(bool randomScore) {
    pSamplwhk->pPianoRoll->Start();
}
H. Guijt
  • 3,325
  • 11
  • 16
  • Now I see what's the problem. Since it add "once", IPianoRoll become always after IMidiEngine. So IMidiEngine don't know IPianoRoll's Start method, right? Why spearate files will fix the problem? That's what I don't udnerstand. At compile time first if include .h, than "compile" .cpp? – markzzz Aug 01 '16 at 09:37
  • 1
    You must make sure the definition of a class is seen before you are allowed to use it. My suggested solution does this: it moves the function body to a later point in the compilation, where both definitions have already been seen by the compiler. – H. Guijt Aug 01 '16 at 09:46
  • 1
    @paizza - In the .cpp file *everything* is included first - so visible in the function bodies. In a header file you cannot see what comes in the next header. – Bo Persson Aug 01 '16 at 09:46
  • Now it starts to make sense why there are .cpp and .h files :) – markzzz Aug 01 '16 at 09:56