Please refresh my knowledge of forward declarations...

Started by
8 comments, last by rip-off 12 years, 11 months ago
Ok, so I have two classes that need to know about each other:

#ifndef __SCENEMANAGER_H__
#define __SCENEMANAGER_H__

#pragma once

#include <vector>
#include <string>
#include <log4cplus/logger.h>
#include <log4cplus/configurator.h>

using namespace log4cplus;
using namespace std;

//Forward declaration, to avoid having to include "UIScene.h".
class UIScene;

class SceneManager
{
private:
vector<UIScene> m_Scenes;
public:
void LoadInitialScreen(string Path);
void AddScreen(UIScene Screen);
};

#endif



#ifndef __UISCENE_H__
#define __UISCENE_H__

#pragma once

#include <vector>
#include <string>
#include "UIBackground.h"
#include "SceneManager.h"
#include "libfar.h"

using namespace std;

class UIScene
{
private:
string m_ArchivePath;
SceneManager m_SceneMgr;

vector<UIBackground> m_Backgrounds;
public:
UIScene(SceneManager SceneMgr, string ArchivePath);
void LoadBackground(int ID);
};

#endif



SceneManager.h compiles perfectly, and I didn't really have a problem until I added the method AddScreen(UIScene Screen) to ScreenManager.

void SceneManager::AddScreen(UIScene Screen)
{
m_Scenes.push_back(Screen);
}



This code (in SceneManager.cpp) gives me the following error:


Error 1 error C2027: use of undefined type 'UIScene

Even though UIScene has been forwardly declared in 'SceneManager.h'!
What gives?
Advertisement
As far as I know you can NOT use whole Classes in your header with forward declarations.

If I am right, the problem occurs due to the fact that classes have different sizes and the compiler does not know the size of UIScene because you declare it forwardly.

You can fix this Problem by taking pointers of UIScene instead of the whole class. Pointers always have the same size.

Hope this helps.

greetings


Fabbo


Edit: you just have to do one of the include guards. You can choose
#pragma once
or you can choose

#ifndef __UISCENE_H__
#define __UISCENE_H__
//stuff here

#endif
E=mc^2 + 2d6
Thanks for your reply!

I changed the method to:

void SceneManager::AddScreen(UIScene *Screen)
{
m_Scenes.push_back(*Screen);
}



Now I get:


Error 1 error C2036: 'UIScene *const ' : unknown size
class SceneManager
{
private:
vector<UIScene> m_Scenes; //you have to have a pointer here too
public:
void LoadInitialScreen(string Path);
void AddScreen(UIScene* Screen);
};


Did you change the
vector<UIScene> m_Scenes;

to

vector<UIScene*> m_Scenes;

And if you did, have you included the UIScene.h in your cpp file?
E=mc^2 + 2d6
Your class makes no sense. Each UIScene contains a discrete SceneManager. The SceneManager has a list of UIScenes. How can you construct an instance of this class?

One of these will need to change to some form of reference to make sense. For example, the UIScene might store a (smart) pointer to the SceneManager, or vice versa. Or see if you can factor out the code that requires knowledge of the "parent" relationship.

class SceneManager
{
private:
vector<UIScene> m_Scenes; //you have to have a pointer here too
public:
void LoadInitialScreen(string Path);
void AddScreen(UIScene* Screen);
};


Did you change the
vector<UIScene> m_Scenes;

to

vector<UIScene*> m_Scenes;

And if you did, have you included the UIScene.h in your cpp file?


I didn't change it because I thought I didn't have to. I mean, I'm using indirection to access the instance in my method. But I'll try to change it...

Your class makes no sense. Each UIScene contains a discrete SceneManager. The SceneManager has a list of UIScenes. How can you construct an instance of this class?

One of these will need to change to some form of reference to make sense. For example, the UIScene might store a (smart) pointer to the SceneManager, or vice versa. Or see if you can factor out the code that requires knowledge of the "parent" relationship.


It makes perfect sense. All UIScene instances are being initialized from Lua, and with the same SceneManager instance (which is globally available to Lua through luabind).

And changing vector<UIScene> to vector<UIScene*> made my code compile, finally. However, I'm not sure if it is actually possible to pass a pointer to an object from Lua. :( I'll have to see about that..
The part with the
vector<UIScene*>
is the same thing like before. The Compiler did not know the size of UIScene so i could not allocate the memory.

With the issue about passing a pointer through the script. I think there is a possibility but a dirty one. I did not test it so i might not work.


You could interpret your pointer (depending on the system architecture (32 bit or 64 bit)) as an Integer or something. It should be easy to give that to a script.

//Let's say you have a pointer of a class called CToScript with the name m_toScript

//I do not know if it works
unsigned int* m_pointerToPass= (unsigned int*) &m_ToScript;

//It would be easier to use a union or sth. like that.

E=mc^2 + 2d6

And changing vector<UIScene> to vector<UIScene*> made my code compile, finally. However, I'm not sure if it is actually possible to pass a pointer to an object from Lua. :( I'll have to see about that..


It's been a while but I am pretty sure this is a bad idea. However, you could allocate your objects in a data structure like a map<> and pass the key in instead. Would be a much safer design.

All UIScene instances are being initialized from Lua, and with the same SceneManager instance (which is globally available to Lua through luabind).[/quote]
Your class takes the scene manager by value. All UIScene instances have copies of the SceneManager at the time they were created. I imagine this is not what you want.

This topic is closed to new replies.

Advertisement