4

I'm having some troubles where a function isn't returning the right type, because a class isn't defined. I'm using a factory pattern.

The two error messages that I'm getting are:

'return': cannot convert from 'DLA *' to 'Layer *'

and:

'Layer': base class undefined (compiling source file src\Layer.cpp)

and this same error message is repeated for every file that includes Layer.h.

Here is what my class that inherits from Layer looks like (DLA.h):

#pragma once

#ifndef _DLA
#define _DLA

#include "ofMain.h" 
#include "ofxGui.h"
#include "Layer.h"

class DLA: public Layer
{
public:
    DLA();
    void setup();
    void update();
    void draw();

private:
};

#endif

and here is my Layer class header (Layer.h):

#pragma once

#ifndef _LAYER
#define _LAYER

#include "ofMain.h" 
#include "ofxGui.h"
#include "DLA.h"

enum SceneType
{
    Scene_None,
    Scene_Default,
    Scene_DLA,
};

class Layer
{

public:

    void setup();
    void update();
    void draw();
    static Layer *CreateSimulation(SceneType Type);


private:
};

#endif

The function which is failing is this one, situated in Layer.cpp:

Layer *Layer::CreateSimulation(SceneType Type)
{
    switch (Type)
    {
    case Scene_None:
    default:
        return nullptr;
    case Scene_DLA:
        return new DLA();
    }
}

I've tried everything I could find on Stack Overflow that had similar issues to mine but I've seen some people recommend very subtle code indentation to fix this, so I'm really lost as to find where the problem is.

enter image description here

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Kaspie
  • 187
  • 11
  • 2
    With long strings of compilation error messages it's usually not worth your time to solve any error except the first one. Many of the following errors are caused by the first error, and will disappear (or change) once you solve that. Based on that - what's the first error in your chain of compilation errors, exactly as your compiler outputs it (word for word)? – JohnFilleau May 14 '20 at 16:18
  • 6
    You should remove `#include "DLA.h"` from `Layer.h`. – Adrian Mole May 14 '20 at 16:18
  • Do you include "Layer.h" in "Layer.cpp"? – ALX23z May 14 '20 at 16:22
  • 1
    Probably not going to bite you, but when it does misusing an underscore can give very bizarre, almost inscrutable results. Give [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) a read for details. – user4581301 May 14 '20 at 16:22
  • I need the `#include "DLA.h"` inside the Layer.h because of the `Layer *Layer::CreateSimulation(SceneType Type)` function that I mention at the end of my post that needs to create a DLA object. I've added an image with the error messages in the original post and yes I do include Layer.h in Layer.cpp – Kaspie May 14 '20 at 16:26
  • @Asymetr can't you place that function in the corresponding cpp file? – Empty Space May 14 '20 at 16:28
  • that wouldn't feel heriarchically correct as _DLA_ is one of the many simulations that inherit from _Layer_. I've managed to solve this by following @ALX23z and removing `#include "DLA.h"` from **Layer.h** and including it in **Layer.cpp**. But Ive never seen includes in .cpp from exterior classes. Is this the correct way to go at it ? – Kaspie May 14 '20 at 16:30
  • @Asymert the other guy first suggested about circular include dependencies... Yes, you include in .cpp whatever you don't need users to see. Also you should read about polymorphism / abstract classes / virtual functions (all three are more or less the same thing) as the way you wrote your code strongly suggests you want one thing but you implement it incorrectly. – ALX23z May 14 '20 at 16:54
  • I'm following advice and tutorial on Factory methods to implement a scene changing system where layers are loaded with one simulation at a time (DLA being one of these simulations) and can be changed via a function. But I'm having a lot of troubles because I'm new to c++ and every new wall I hit feels like 3 branches of hours of tutorials to choose from. I appreciate the help. Hitting a new wall right now where the return object of my CreateSimulation is of type Layer when I actually want it to be of the requested simulation type , uuugh, Ill read more ! thanks – Kaspie May 14 '20 at 17:10
  • @ALX23z The 'other' guy has posted an answer - hope it helps! ‎ Feel free to critique the arguments and suggestions made therein. – Adrian Mole May 14 '20 at 17:22

1 Answers1

2

As they stand, your header files induce circular dependency, even though the #pragma once (and other) guards prevent any actual 'infinite recursion'. Let's look at the sequence of code, from the compiler's point-of-view, when compiling the Layer.cpp file (or any other '.cpp' source that has #include "Layer.h" in it).

The compiler encounters #include "Layer.h" (the first time it has done so - the guards won't be 'triggered'), so it duly replaces that line with the contents of the indicated header. In that content, it encounters #include "DLA.h" (we can ignore the other headers included in this discussion, assuming that they aren't relevant to the problem in hand). So, it then duly replaces that line with the contents of the DLA.h header, at which point it will come across this:

#include "Layer.h"

class DLA: public Layer
{

Now, here, when it replaces #include "Layer.h" with the header content, that content will be 'empty' (because of the guards, as it has already included that header once). Thus, when the public Layer code is encountered, it is an error, because that class has not yet been defined, or even declared as a class.

So, if you really insist on having the #include "DLA.h" line in Layer.h, then it must be placed after the definition of the Layer class.

However, a far better way would be to remove #include "DLA.h" from Layer.h, and only place it in source (.cpp) files that actually need it (like Layer.cpp). This would work well:

// Layer.cpp
#include "Layer.h"
#include "DLA.h"   // At this point, references to the Layer class in DLA.h will be fine!

//...

Layer *Layer::CreateSimulation(SceneType Type)
{
    switch (Type)
    {
    case Scene_None:
    default:
        return nullptr;
    case Scene_DLA:
        return new DLA();
    }
}

Feel free to as k for any further clarification and/or explanation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83