Accessing class instances that are declared in another source file

Started by
2 comments, last by Supercharger 16 years, 11 months ago
I've recently started to learn C++ with SDL and have managed to get started with the basics. As I thought it would make sence to learn dividing the source code into multiple source files as early as possible, I immediately ran into problems with classes. Yes, I know about the "Organizing Code Files in C and C++" guide by Ken Sizer (http://www.gamedev.net/reference/programming/features/orgfiles/default.asp) and trust me, I've read that thing over and over again but haven't managed to get my code working. Even though I'm pretty sure this is just me not understanding something simple I guessed it wouldn't hurt to ask. As I'm a beginner and don't speak English natively, I apologize about any spelling errors or misused terms etc. So, let's say I have five files: main.cpp, graphics.h, graphics.cpp, game.h and game.cpp. Below are their simplified contents. graphics.h
#ifndef INC_GRAPHICS_H
#define INC_GRAPHICS_H

// Class prototype for graphics
class GraphObject
{
 public:
 void GraphLoad();
 void GraphDraw();
};

#endif
graphics.cpp
#include "graphics.h"

void GraphObject::GraphLoad()
{
 // Stuff for loading a image file.
}

void GraphObject::GraphDraw()
{
 // Stuff for drawing the image on the screen.
}
game.h
#ifndef INC_GAME_H
#define INC_GAME_H

// An example function
void GameDrawImage();

#endif
game.cpp
#include "game.h"
#include "graphics.h"

void GameDrawImage()
{
 // My goal is to use this function to access the 'image' instance of GraphObject
 // that is created in main.cpp, load a image into it and draw it on screen.
 image.GraphLoad();
 image.GraphDraw();
}
main.cpp
#include "gfx.h"
#include "game.h"

// Let's create a couple of instances of the GraphObject class.
// Is it ok to place these here? Not that I would as I would most likely
// make some manner of function to load all the images at once, but I'm
// trying to make these class instances available for all source files.
GraphObject background;
GraphObject image;

int main(int argc, char* args[])
{
 // Load a background image
 background.GraphLoad(...);
 // Draw the background
 background.GraphDraw(...);
 
 // Above gets drawn correctly.
 
 // Now I'm supposed to use a function from game.cpp to load and draw the other image.
 // This one fails as it cannot access the 'image' instance of GraphObject.
 GameDrawImage();
 
 return 1;
}
Now, am I getting the whole idea of classes wrong here or is there some neat way to make the game.cpp capable of accessing the class instance that's declared in main.cpp? I know that the "GraphObject image" gets drawn if I move it's declaration from main.cpp to within the GameDrawImage() function in game.cpp, but that doesn't solve my problem here. When I try to compile something that's built as above I get the "undeclared identifier" and "'.GraphLoad' must have class/struct/union" errors in game.cpp. I'd greatly appreciate if someone could ease my headache with this one. And I'm sorry if there already are similar threads as I couldn't really figer out what to type into the search.
Advertisement
Your other source files don't have any reference to the instances image and background. The source files are compiled one at a time then linked together, so when it's compiled, each source file doesn't "know" what's in the others.

You can tell it that 'image' exists by saying 'extern GraphObject image;' in files that need to use the instance 'image'. Or you could put 'extern GraphObject image;' in a header file, and any cpp file that includes that header file can use the instance 'image'.

Many people consider it bad practice to use instances that are global like this, though; in a 'proper' OOP design, you would have member variables or pointers or references that point to shared variables like image, not global variables.
Also, instead of having global instances being invoked directly inside of the function, have void GameDrawImage() take an argument of type GraphObject e.g.

bool GameDrawImage( GraphObject& image )
{
bool success = image.GraphLoad(...);

if( !success )
return false;

image.GraphDraw(...);

return true;
}

You should also generally check that an image was loaded correctly, this makes it easier for debugging etc.
Show A Man A Program, Frustrate Him For A Day...Teach A Man To Program, Frustrate Him For The Rest Of His Life...
For some reason I totally forgot about 'extern'. Yes, I know I shouldn't use global variables and most probably I'll have to rework my entire program design. I think I'll try passing variables directly into functions, just like DrunkenBrit suggested.

Thanks nagromo and DrunkenBrit. Now I can finally move on to other stuff.

This topic is closed to new replies.

Advertisement