Class and pointer problems

Started by
11 comments, last by rip-off 13 years, 9 months ago
This is quite a big problem, please can you take the time to read this post and help me.

This is my setup:

I have 4 files that the problem relates to:

E_GM.h
E_GM.cpp
E_LUA.h
E_LUA.cpp
E_MAP.h
E_MAP.cpp

E_GM is a class that all of my game classes can communicate with, so insted of the player class communicating with the map class directly, they all communicate with E_GM and E_GM can communicate with the other classes. This design, in my opinion, saves me declaring lots of pointers to loads of classes.

So...

E_LUA is a class that deals with my lua scripts. It can communicate with E_GM.

E_MAP is a class that deals with maps. It can also communicate with E_GM.

On to the problem:

I am writing a function that can be called by lua scripts. That function is supposed to load a map. It can load a map by using the E_MAP class. But they dont communicate directly. E_GM has a function that load maps. In the E_GM map loading function, it calls the E_MAP map loading function.

So to achieve this, i think i need a foward class declaration in E_MAP.h and E_LUA.h to class E_GM.

E_GM.h includes E_LUA.h and E_MAP.h
E_GM.cpp includes E_LUA.h and E_MAP.h
E_LUA.h has a foward class declaration of E_GM
E_LUA.cpp includes E_GM
E_MAP.h has a foward class declaration of E_GM
E_MAP.cpp includes E_GM

E_LUA and E_MAP each keep a pointer to E_GM.

But when i call this line in E_LUA.cpp :
E_GM_POINTER->LoadMap(MapFileName);


Visual C++ 2008 gives me this,
error C2227: left of '->LoadMap' must point to class/struct/union/generic type

when i have declared E_GM_pointer in the E_LUA.h as a pointer to the forward class declaration of E_GM.

Do you understand my problem?
Problerly not, heres the files anyway:
WARNING-they include alot of stuff that does not relate to the problem

E_GM.h
#ifndef E_GM_H#define E_GM_H#include "E_LUA.h"#include "E_GUI.h"#include "E_PLAYER.h"#include "E_MAP.h"class E_GM{	private:		//communication		E_LUA* E_LUA_PTR;		E_GUI* E_GUI_PTR;		E_PLAYER* E_PLAYER_PTR;		E_MAP* E_MAP_PTR;	public:		//communication		void Set_ELUA_Com(E_LUA* point);		void Set_EGUI_Com(E_GUI* point);		void Set_EPLAYER_Com(E_PLAYER* point);		void Set_EMAP_Com(E_MAP* Point);		//E_LUA functions		//E_GUI functions		//E_PLAYER functions		//E_MAP functions		void LoadMap(string filename);};#endif


E_GM.cpp
#include "E_GM.h"#include "E_LUA.h"#include "E_PLAYER.h"void E_GM::Set_ELUA_Com(E_LUA *point){	E_LUA_PTR = point;}void E_GM::Set_EGUI_Com(E_GUI* point){	E_GUI_PTR = point;}void E_GM::Set_EPLAYER_Com(E_PLAYER* point){	E_PLAYER_PTR = point;}void E_GM::Set_EMAP_Com(E_MAP* point){	E_MAP_PTR = point;}void E_GM::LoadMap(string filename){	//clean up the old map	E_MAP_PTR->CleanUpShit();	//load a new one	E_MAP_PTR->LoadMap(filename);}


E_LUA.h
#ifndef E_LUA_H#define E_LUA_H#include "E_CORE.h"#include <string>extern "C" {	#include "lua.h"	#include "lualib.h"	#include "lauxlib.h"}using namespace std;//forward class declaration for E_GM//needed for 2-way communicationclass E_GM;//All LUA functions//int class//static int LUA_Print(lua_State *L);//static int LUA_DrawImg(lua_State *L);class E_LUA{	private:		lua_State* L;		//pointer to E_CORE object(for communication)			E_CORE* E_CORE_pointer;			E_GM* E_GM_pointer;	public:		//initialization and engine functions		bool Init();		void End();		//pointers		void Set_ECORE_Pointer(E_CORE* ptr);		void Set_EGM_Pointer(E_GM* ptr);		//lua		lua_State* GetLuaState();		void ExecuteScript(string filename);		//functions		void RegisterAllFunctions();		//lua functions		static int LUA_Print(lua_State *L);		static int LUA_LoadMap(lua_State *L);};#endif


E_LUA.cpp
#include <string>#include <iostream>#include "E_CORE.h"#include "E_LUA.h"#include "E_GM.h"extern "C" {	#include "lua.h"	#include "lualib.h"	#include "lauxlib.h"}using namespace std;//all LUA functionsint E_LUA::LUA_Print(lua_State *L){	string b = lua_tostring(L, lua_gettop(L));	cout << b << endl;	return 0;}int E_LUA::LUA_LoadMap(lua_State *L){	//first get the argument	string MapFileName = lua_tostring(L, lua_gettop(L));	//ask the Game Manager to load a map for us	E_GM_pointer->LoadMap(MapFileName);	return 0;}bool E_LUA::Init(){	L = lua_open();	luaL_openlibs(L);	return true;}void E_LUA::End(){	lua_close(L);}void E_LUA::ExecuteScript(string filename){	cout << "Executing Script " << filename << endl;	luaL_dofile(L,filename.c_str());	cout << "Done Executing Script " << filename << endl;}lua_State* E_LUA::GetLuaState(){	return L;}void E_LUA::RegisterAllFunctions(){	lua_register(L, "LUA_Print", LUA_Print);	lua_register(L, "LUA_LoadMap", LUA_LoadMap);}void E_LUA::Set_ECORE_Pointer(E_CORE* ptr){	E_CORE_pointer = ptr;}void E_LUA::Set_EGM_Pointer(E_GM *ptr){	E_GM_pointer = ptr;}


E_MAP.h
#ifndef E_MAP_H#define E_MAP_H#include "SDL.h"#include "E_CORE.h"#include <string>#include <fstream>using namespace std;//needed for 2-way communication with the Game Managerclass E_GM;class E_MAP_TILESET{	public:		//communication		E_CORE* E_CORE_pointer;		//data		string Filename;		SDL_Surface* Texture;		SDL_Rect Clips[640];		int NumberOfTiles;		//functions		void Load(string Path);};class E_MAP_TILE{	public:	//communication	E_CORE* E_CORE_pointer;	//data	SDL_Rect BoundingBox;	int TilesetNumber;	int ClipNumber;	bool IsBlank;	//functions	void Draw();};class E_MAP{	private:		E_CORE* E_CORE_pointer;		E_GM* E_GM_pointer;		framerate* Framerate_pointer;	public:		//communication		void Set_ECORE_Pointer(E_CORE* ptr);		void Set_EGM_Pointer(E_GM* ptr);		void Set_Framerate_pointer(framerate* ptr);		//data		E_MAP_TILESET* Tilesets[7];		E_MAP_TILE* TilesLayer1[475];		E_MAP_TILE* TilesLayer2[475];		E_MAP_TILE* TilesLayer3[475];		int MapWidthInPixels;		int MapHeightInPixels;		int MapWidthInTiles;		int MapHeightInTiles;		int MapPixelSurfaceArea;		int MapTotalTiles;		ifstream MapFile;		string MapName;		int TotalMapTilesets;		//funtionallity		void LoadMap(string Path);		void CleanUpShit();		//tiles		void DrawTile(int TileNumberOnMap, int Layer);		void DrawMapLayer1();		void DrawMapLayer2();		void DrawMapLayer3();};#endif


E_MAP.cpp
#include "SDL.h"#include "E_MAP.h"#include <string>#include <fstream>#include <iostream>using namespace std;//tilesetvoid E_MAP_TILESET::Load(string Path){	Texture = E_CORE_pointer->LoadImg(Path);	if(Texture == NULL)	{		cout << "WARNING-Could not load " << Path << endl;	}	int Height = Texture->h;	int TileHeight = Height/32;	const int Width = 256;			//the width for all tilesets is 256	const int TileWidth = 8;		//8 tiles in a row	NumberOfTiles = TileHeight * TileWidth;	//now set the clips for the tileset	int xpos, ypos;	xpos = 0;	ypos = 0;	for(int t=0; t<NumberOfTiles; t++)	{		Clips[t].x = xpos;		Clips[t].y = ypos;		Clips[t].w = 32;		Clips[t].h = 32;		xpos += 32;		if(xpos > 256)		{			ypos += 32;			xpos = 0;		}	}}//tilevoid E_MAP_TILE::Draw(){	//not used}//map//communicationvoid E_MAP::Set_ECORE_Pointer(E_CORE* ptr){	E_CORE_pointer = ptr;}void E_MAP::Set_EGM_Pointer(E_GM* ptr){	E_GM_pointer = ptr;}void E_MAP::Set_Framerate_pointer(framerate* ptr){	Framerate_pointer = ptr;}void E_MAP::LoadMap(string Path){	cout << "Loading " << Path << endl;	string TilesetPath;	//first open the map file	MapFile.open(Path.c_str());	//get the map name	getline(MapFile, MapName);	cout << "Map name is " << MapName << endl;	//get how many tilesets there are	MapFile >> TotalMapTilesets;	cout << "This map has " << TotalMapTilesets << " tilesets\n";	//get all the tileset paths	TotalMapTilesets = 0;	for(int t=0; t<7; t++)	{		MapFile >> TilesetPath;		if(TilesetPath != "NADA")		{			TotalMapTilesets ++;			Tilesets[t] = new E_MAP_TILESET();			Tilesets[t]->Filename = TilesetPath;			Tilesets[t]->E_CORE_pointer = E_CORE_pointer;			Tilesets[t]->Load(TilesetPath);			cout << TilesetPath << endl;		}		else		{			Tilesets[t] = new E_MAP_TILESET();			Tilesets[t]->Filename = "NADA";			Tilesets[t]->E_CORE_pointer = E_CORE_pointer;		}	}	//get the map dimensions	MapFile >> MapWidthInTiles;	cout << "The map width in tiles is " << MapWidthInTiles << endl;	MapFile >> MapHeightInTiles;	cout << "The map height in tiles is " << MapHeightInTiles << endl;	MapWidthInPixels = MapWidthInTiles*32;	MapHeightInPixels = MapHeightInTiles*32;	MapPixelSurfaceArea = MapHeightInPixels*MapWidthInPixels;	MapTotalTiles = MapWidthInTiles*MapHeightInTiles;	cout << "The map width in pixels is " << MapWidthInPixels << endl;	cout << "The map height in pixels is " << MapHeightInPixels << endl;	cout << "The map pixel surface area is " << MapPixelSurfaceArea << endl;	cout << "The total tiles on the map is " << MapTotalTiles << endl;	cout << "Loading the first layer of tiles...\n";	//load the first layer of tiles	int xposition, yposition, Tilesetid, Placeintileset, isblank;	xposition = 0;	yposition = 0;	Tilesetid = 0;	Placeintileset = 0;	isblank = 0;	for(int t=0; t<MapTotalTiles; t++)	{		//for each tile		//read everything		MapFile >> Tilesetid;		MapFile >> Placeintileset;		MapFile >> xposition;		MapFile >> yposition;		MapFile >> isblank;		xposition *= 32;		yposition *= 32;		//make the tile		TilesLayer1[t] = new E_MAP_TILE();		if(isblank == 1)		{			TilesLayer1[t]->IsBlank = true;		}		else		{			TilesLayer1[t]->IsBlank = false;		}		TilesLayer1[t]->BoundingBox.x = xposition;		TilesLayer1[t]->BoundingBox.y = yposition;		TilesLayer1[t]->BoundingBox.w = 32;		TilesLayer1[t]->BoundingBox.h = 32;		TilesLayer1[t]->ClipNumber = Placeintileset;		TilesLayer1[t]->TilesetNumber = Tilesetid;		TilesLayer1[t]->E_CORE_pointer = E_CORE_pointer;	}	cout << "Loaded the first layer!\n";	cout << "Loading the second layer of tiles...\n";	//load the second layer of tiles	xposition = 0;	yposition = 0;	Tilesetid = 0;	Placeintileset = 0;	isblank = 0;	for(int t=0; t<MapTotalTiles; t++)	{		//for each tile		//read everything		MapFile >> Tilesetid;		MapFile >> Placeintileset;		MapFile >> xposition;		MapFile >> yposition;		MapFile >> isblank;		xposition *= 32;		yposition *= 32;		//make the tile		TilesLayer2[t] = new E_MAP_TILE();		if(isblank == 1)		{			TilesLayer2[t]->IsBlank = true;		}		else		{			TilesLayer2[t]->IsBlank = false;		}		TilesLayer2[t]->BoundingBox.x = xposition;		TilesLayer2[t]->BoundingBox.y = yposition;		TilesLayer2[t]->BoundingBox.w = 32;		TilesLayer2[t]->BoundingBox.h = 32;		TilesLayer2[t]->ClipNumber = Placeintileset;		TilesLayer2[t]->TilesetNumber = Tilesetid;		TilesLayer2[t]->E_CORE_pointer = E_CORE_pointer;	}	cout << "Loaded the second layer!\n";	cout << "Loading the third layer of tiles...\n";	//load the second layer of tiles	xposition = 0;	yposition = 0;	Tilesetid = 0;	Placeintileset = 0;	isblank = 0;	for(int t=0; t<MapTotalTiles; t++)	{		//for each tile		//read everything		MapFile >> Tilesetid;		MapFile >> Placeintileset;		MapFile >> xposition;		MapFile >> yposition;		MapFile >> isblank;		xposition *= 32;		yposition *= 32;		//make the tile		TilesLayer3[t] = new E_MAP_TILE();		if(isblank == 1)		{			TilesLayer3[t]->IsBlank = true;		}		else		{			TilesLayer3[t]->IsBlank = false;		}		TilesLayer3[t]->BoundingBox.x = xposition;		TilesLayer3[t]->BoundingBox.y = yposition;		TilesLayer3[t]->BoundingBox.w = 32;		TilesLayer3[t]->BoundingBox.h = 32;		TilesLayer3[t]->ClipNumber = Placeintileset;		TilesLayer3[t]->TilesetNumber = Tilesetid;		TilesLayer3[t]->E_CORE_pointer = E_CORE_pointer;	}	cout << "Loaded the third layer!\n";	//finally close the map	cout << "Loaded Map!\n";	MapFile.close();}void E_MAP::CleanUpShit(){	//clean up tilesets	for(int t=0; t < TotalMapTilesets; t++)	{		cout << "Cleaning up tileset " << t << endl;		SDL_FreeSurface(Tilesets[t]->Texture);	}}void E_MAP::DrawTile(int TileNumberOnMap, int Layer){	if(Layer == 1)	{		E_CORE_pointer->DrawImg(			TilesLayer1[TileNumberOnMap]->BoundingBox.x,														   //x position			TilesLayer1[TileNumberOnMap]->BoundingBox.y,														   //y position			Tilesets[TilesLayer1[TileNumberOnMap]->TilesetNumber]->Texture,																	   //the image to draw			E_CORE_pointer->GetScreenSurface(),																	   //where to draw it			&Tilesets[TilesLayer1[TileNumberOnMap]->TilesetNumber]->Clips[TilesLayer1[TileNumberOnMap]->ClipNumber]//the clip		);	}}void E_MAP::DrawMapLayer1(){	//draw layer 1	for(int t=0; t<MapTotalTiles; t++)	{		if(TilesLayer1[t]->IsBlank == false)		{		//for each tile		//draw it		E_CORE_pointer->DrawImg(			TilesLayer1[t]->BoundingBox.x,												//x position			TilesLayer1[t]->BoundingBox.y,												//y position			Tilesets[TilesLayer1[t]->TilesetNumber]->Texture,							//the image to draw			E_CORE_pointer->GetScreenSurface(),											//where to draw it			&Tilesets[TilesLayer1[t]->TilesetNumber]->Clips[TilesLayer1[t]->ClipNumber]	//the clip		);		}	}}void E_MAP::DrawMapLayer2(){	//draw layer 2	for(int t=0; t<MapTotalTiles; t++)	{		//for each tile		//draw it		if(TilesLayer2[t]->IsBlank == false)		{		E_CORE_pointer->DrawImg(			TilesLayer2[t]->BoundingBox.x,												//x position			TilesLayer2[t]->BoundingBox.y,												//y position			Tilesets[TilesLayer2[t]->TilesetNumber]->Texture,							//the image to draw			E_CORE_pointer->GetScreenSurface(),											//where to draw it			&Tilesets[TilesLayer2[t]->TilesetNumber]->Clips[TilesLayer2[t]->ClipNumber]	//the clip		);		}	}}void E_MAP::DrawMapLayer3(){	//draw layer 3	for(int t=0; t<MapTotalTiles; t++)	{		//for each tile		//draw it		if(TilesLayer3[t]->IsBlank == false)		{		E_CORE_pointer->DrawImg(			TilesLayer3[t]->BoundingBox.x,												//x position			TilesLayer3[t]->BoundingBox.y,												//y position			Tilesets[TilesLayer3[t]->TilesetNumber]->Texture,							//the image to draw			E_CORE_pointer->GetScreenSurface(),											//where to draw it			&Tilesets[TilesLayer3[t]->TilesetNumber]->Clips[TilesLayer3[t]->ClipNumber]	//the clip		);		}	}}


Thats all, sorry for the mega-huge post, i wanted to make sure my problem was clear. Thanks for any help.
Advertisement
What does E_CORE.h look like?
Here you go:

E_CORE.h
#ifndef E_CORE_H#define E_CORE_H#include <iostream>#include <fstream>#include <string>#include "windows.h"#include "SDL.h"using namespace std;#define DIRECTION_UP 1#define DIRECTION_DOWN 2#define DIRECTION_LEFT 3#define DIRECTION_RIGHT 4class E_CORE{	private:		//WINDOW PROPERTIES			string WindowCaption;			int WindowWidth;			int WindowHeight;			bool WindowIsFullscreen;			SDL_Surface* ScreenPointer;			HWND hWnd; //this is used for hiding the command prompt window			bool WindowIsShowing;		//EVENTS			SDL_Event Event;		//OTHER			ofstream logger;	public:		//Initialization and ending Functions		bool Init();		bool ScreenInit(int width, int height, bool fullscreen, string caption);		bool End();		//Data retrieving functions		SDL_Surface* GetScreenSurface();		bool GetWindowIsFullscreen();		int GetWindowHeight();		int getWindowWidth();		string GetWindowCaption();		//window functions		bool UpdateScreen();		void EHideWindow();		void EShowWindow();		bool GetWindowShowing();		//event handling functions		SDL_Event GetEventPointer();		SDL_Event *GetEventPointerP();		//image functions		SDL_Surface* LoadImg(string filename);		void DrawImg(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip);		//utility functions		int Round(float number);		void Log(string message);};//Timer Class/*Thankyou:	http://lazyfoo.net/SDL_tutorials/lesson13/index.php*/class Timer{    private:    //The clock time when the timer started    int startTicks;        //The ticks stored when the timer was paused    int pausedTicks;        //The timer status    bool paused;    bool started;        public:    //Initializes variables    Timer();        //The various clock actions    void start();    void stop();    void pause();    void unpause();        //Gets the timer's time    int get_ticks();        //Checks the status of the timer    bool is_started();    bool is_paused();    };//Framerate Class/*Thankyou:	http://www.gamedev.net/reference/articles/article1382.asp*/class framerate{public:  float         targetfps;  float         fps;  LARGE_INTEGER tickspersecond;  LARGE_INTEGER currentticks;  LARGE_INTEGER framedelay;	  float         speedfactor;			  void          Init(float tfps);  void          SetSpeedFactor();};#endif


Hiding the command prompt-like window doesnt work.

EDIT:

E_CORE deals with lower level stuff, other classes can have direct communication with it. E_CORE does not need to communicate with any of the higher-level classes.

[Edited by - Lith on July 17, 2010 9:49:53 AM]
Anyone?
It took me 10 minutes to notice this, but you are declaring:
E_GM* E_GM_pointer;


In the header, but using

E_GM_POINTER->LoadMap(MapFileName);


when you describe the problem (notice the upper case POINTER). It doesn't show up like this in the code you've posted, but maybe there's a point to start.

I can't figure anything else that is wrong with your code: it should work. You should let the compiler output the preprocessed file of E_LUA.cpp, maybe this gives you a hint what's wrong (maybe there's some macro magic going on).

In case you don't know how to do that, right-click your project settings, go to properties, c/c++, preprocessor and set "Preprocess to File" to yes (I've only opened Visual Studio 2010, so it might be a bit different in 2008).
By the look of it, you are not including E_GM.h in E_MAP.cpp so the forward declarations are not completed before being dereferenced.
Thanks for the replys.

@SiS-Shadowman:

I dont use the capitialised version in the actual source code.

Thanks for the suggestion of the preprocessing thing. After some googling i found out how to do it the 2008. But now when i compile it with the /P thing, it says it cant find E_CORE.obj after it's compiled everything. When i take of the /P thing, it gives me the same error?

I will now try including the E_GM.h in E_MAP.cpp and see what happens

EDIT:
I got the same error.
Hey,

I'm fairly sure that this line is your problem (in E_LUA.h):

static int LUA_LoadMap(lua_State *L);


Because that member is declared static it isn't associated to any particular instance of the class - and therefore wouldn't have access to any non-static member variables of E_LUA (in this instance E_GM_Pointer).

Ben
Thanks for the reaply, thats a good idea, so i got rid of the "static" and i got another error:

error C3867: 'E_LUA::LUA_LoadMap': function call missing argument list; use '&E_LUA::LUA_LoadMap' to create a pointer to member


It was on this line:
lua_register(L, "LUA_LoadMap", LUA_LoadMap);


Just some info:
in the header file i removed the "static", but in cpp file, there was no "static" in the first place. I dont know why, because i was following what i did on the first function, "LUA_Print".

So insted of that, i put this:
lua_register(L, "LUA_LoadMap", &E_LUA::LUA_LoadMap);


And i got this error:
error C2664: 'lua_pushcclosure' : cannot convert parameter 2 from 'int (__thiscall E_LUA::* )(lua_State *)' to 'lua_CFunction'


[Edited by - Lith on July 19, 2010 2:41:19 AM]
Does anyone know what could be wrong?

This topic is closed to new replies.

Advertisement