1

My problem is about including header files. I don't want to include headers in other header file so when I need it, I always write declarations the beginning of the header and include in the cpp files as you can see, but this time it does not work.

BaseModel.h

#pragma once
#include <vector>
#include <unordered_map>
#include <string>

class Texture
{
public:
    void addTexture2D(const char* keyname, int filter, int wrap, int internalformat, int format, int width, int height, unsigned char* texelData);
    void addTextureCubeMap(const char* keyname, int filter, int wrap, int internalformat, int format, int width, int height, unsigned char* texelData);
    void bindTexture(const char* keyname, unsigned int additionalUnits = 0);

    inline static Texture* const getInstance() { return m_instance; }
private:
    static Texture* const m_instance;
    std::unordered_map<const char*, unsigned int> m_textureIDs;

    Texture();
    ~Texture();

    friend void terminateEngine();
};

class Mesh
{
public:
    Mesh();
    Mesh(const Mesh& copy) = delete;
    Mesh(Mesh&& move) noexcept;
    ~Mesh();

    void addVertexBuffer(size_t sizeInByte, const void* data, const unsigned int* perAttribSize, const unsigned int attribCount, unsigned int divisorValue, bool isDynamic = false);
    void addIndexBuffer(size_t sizeInByte, const void* data);

    void Bind() const;
    inline const unsigned int& getVertexArrayId() const { return m_vertexArrayID; }

private:
    unsigned int m_attribIndex;
    unsigned int m_vertexArrayID;
    std::vector<unsigned int> m_buffers;
};

class Program
{
public:
    struct Shaders
    {
        unsigned int vertexShader;
        unsigned int tessControlShader;
        unsigned int tessEvaluationShader;
        unsigned int geometryShader;
        unsigned int fragmentShader;
    };

    Program();
    Program(const Program& copy) = delete;
    Program(Program&& move) noexcept;
    ~Program();

    void addShaders(const Shaders& shaders);
    void addComputeShader(const unsigned int computeShader);
    void Bind() const;

    inline const unsigned int& getProgramID() const { return m_programID; }
private:
    unsigned int m_programID;
};

Model.h

#pragma once
#include "Interfaces.h"
#include "glm/glm.hpp"

class Mesh;
class Program;

class Surface
{
public:
    Surface(const unsigned int seed, float chunkSize, float instanceCountperSide);
    Surface(const Surface& copy) = delete;
    Surface(Surface&& move) noexcept = delete;
    ~Surface();

    void Render(const glm::vec3& cameraPos);

private:
    Mesh m_mesh;
    Program m_program;

    unsigned int m_indexCount;

    float a;
    float globaltexCoords[2];

    int m_cameraLoc;
    int m_globaltexCoordloc;
};

In Model.cpp

#include "Model.h"
#include "BaseModel.h"
#include "glad/glad.h"
#include "GLFW/glfw3.h" // Silincek
#include "stb_image.h"
#include "FileIO.h"

The problem says Surface::m_mesh and Surface::m_program are undefined classes 'Mesh' and 'Program' but actually I added them as can be seen in the Model.cpp. Why do I encounter with the this problem?

I have examined the preprocessor file of Model.cpp and there is nothing wrong.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
yigitEmre
  • 31
  • 5
  • You actually can fix the error by switching the order of `#include "BaseModel.h"` and `#include "Model.h"` statements in your `Model.cpp`, but this is very specific fix, your main problem is that `Surface` consists of incomplete classes – The Dreams Wind May 13 '23 at 09:51
  • Does this answer your question? [When does an Incomplete Type error occur in C++](https://stackoverflow.com/questions/44963201/when-does-an-incomplete-type-error-occur-in-c) – The Dreams Wind May 13 '23 at 09:54
  • Incomplete types can only be used in some cases. You could use references/pointers to incomplete types, since the pointer size is independent of the size of the object pointed to, but if you add a member variable of a type to your class, the size of this type needs to be known to the compiler, but this isn't the case for incomplete types. You ***cannot*** keep the `Surface` class as is and have the compiler accept code where it hasn't encountered the `Mesh` and `Program` types before the class definition of `Surface`. – fabian May 13 '23 at 09:58
  • Also why change your mind when you already included your own `Interfaces.h` header in `Models.h` anyways? Leaving the include out of the header file has no real benefit here. Since every translation unit including `Model.h` needs to include `BaseModel.h` or fail compilation, just add the include to the header and remove that pitfall. There's no benefit in having the user worry about including all the necessary dependencies of your headers in the right order... – fabian May 13 '23 at 10:02
  • The reason why I don't want to add BaseModel.h is too big. When I just need to use Surface class in some where I also have to add BaseModel.h which is too big by including unordered_map , vector and string. And also I will add several classes in the future to it. Therefore I am afraid of having too big source files and exe. (Interfaces.h contains just a few pure virtual classes which are quite small) – yigitEmre May 13 '23 at 10:19

1 Answers1

1

To be used as a type specifier of a variable declaration a class declaration shall be complete.

Non-static data members may not have an incomplete type. It is static data members of a class that may have an incomplete type.

At least within the class Surface

class Surface
{
//...
private:
    Mesh m_mesh;
    //...

you declared a data member of the class Mesh that is an incomplete. So the compiler issues an error.

You need to include the header BaseModel.h in the header Model.h

The same you should do relative to other references to using undefined or incomplete classes as for example the class Program

At least you should exchange inclusions of the headers

#include "Model.h"
#include "BaseModel.h"

like

#include "BaseModel.h"
#include "Model.h"

within the module Model.cpp

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335