1
\$\begingroup\$

I have no idea why I'm getting this error except that it has to do with the includes.

Base class header file:

#pragma once

#include "Player.h"
#include "TestObject.h"
#include <glm\glm.hpp>
#include <GL\glew.h>

class GameObject
{
//unrelated code
};

Derived class header file:

#pragma once

#include "GameObject.h"
#include <glm\glm.hpp>
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtc\type_ptr.hpp>

class Player : public GameObject
{
//unrelated code
};

error message:

Error   C2504   'GameObject': base class undefined

And here are the includes for both cpp files:

base:

#include "GameObject.h"
#include "Player.h"
#include <iostream>
#include <glm\glm.hpp>

derived:

#include "Player.h"
#include "GameObject.h"
#include <iostream>
#include <glm\glm.hpp>
\$\endgroup\$
3
  • 1
    \$\begingroup\$ You're having a circular dependency between your headers. I don't remember what it does but you might want to forward declare your dependencies if you only use pointers to them in the header files. (GameObject should not have an #include to Player.) \$\endgroup\$
    – Vaillancourt
    Commented Jul 30, 2018 at 20:08
  • 1
    \$\begingroup\$ GameObject.h includes Player.h. The first real line of code in the resulting stew is class Player : public GameObject, which has not, at that point, been defined. Get rid of your #include "player.h" in GameObject.h. \$\endgroup\$
    – 3Dave
    Commented Jul 30, 2018 at 20:13
  • \$\begingroup\$ Okay it works now, thanks guys. Stupid mistake i know :/ \$\endgroup\$ Commented Jul 30, 2018 at 20:19

1 Answer 1

3
\$\begingroup\$

When the compiler goes to compile your base.cpp file, it runs the preprocessor to perform textual substitution of all #include directives with their contents. This substitution is "dumb," it is effectively a copy-and-paste operation that you can control slightly with other preprocessor directives like #pragma or #ifdef, et cetera.

The first part of this process is to replace #include "GameObject.h", which has a #pragma once. The compiler hasn't copied this file into the resulting TU yet, so it does so, records that it has (for later #pragma once checks) and recursively continues on.

This means the next thing it does is copy in Player.h, which also has a #pragma but also hasn't yet been seen, and thus the copy continues. Then it continues on recursively.

This means the next thing it does is try to replace the #include "GameObject.h" copied in by Player.h. But it has already seen GameObject.h so it skips this line and continues on.

The net result is that after pre-processing your source file is arranged roughly like:

class Player : public GameObject
{
//unrelated code
};

class GameObject
{
//unrelated code
};

This is the actual code the compiler ends up seeing, and naturally can't be compiled because by the time you are defining Player you have not yet defined the base class GameObject.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .