Problems calling constructor

Started by
7 comments, last by nilkn 18 years, 10 months ago
I'm working on a version of Tic Tac Toe, using a new object oriented SDL framework I built myself. Basically, to load an image, you overload the constructor on the SpriteWrapper class (stored in spritewrapper.h and spritewrapper.cpp), passing in the filename and the surface onto which you want the image to be blitted. However, I'm trying to keep my code modular, so a separate function is used to "clean up" by freeing all the surfaces when the program exits. Therefore, the only real way of doing this is to call the constructor like a global variable, outside of any function. When I do this, and call the function to blit the sprite, it doesn't appear on screen. But when I call it within a function (eg int main()), it can be blitted and the screen gets flipped, and the sprite appears on screen. But it's been called locally, so I can't access it in the "clean up" function to free it (I get an undeclared identifier error). The same problem is also seen with the overloaded constructors used to load audio files. Is there a way around this? Sorry if this doesn't seem clear, please let me know if you need further clarification. Thanks in advance, ukdeveloper
Advertisement
I don’t truly understand what your asking, but if I am understanding you correct your problem is that you loose the pointer to the created surface?

One way to solve this problem is to implement surface memory into your engine. Ie have a list of pointers to surfaces (array or dynamic list, your call) that is a global, and where all created surface pointers are stored (note that you could make this list be the actual memory for the surfaces instead, once again your call). Now your garbage collector will iterate through that list and destroy all surfaces there in (or all surfaces tagged to be destroyed).

Sorry if I’m way off track here.
Construction/destruction order is not defined when using global variables. You should therefore be carefull when instanciating or newing globally. If you want to control the order of creation you can make a create/destroy function set.

SpriteWrapper *g_Sprite;void create_sprites(){  g_Sprite = new SpriteWrapper(...);}void destroy_sprites(){  delete g_Sprite;}


It this in the line of what you are looking for?

What does your SpriteWrapper really do? Does it only open the file and fills writes the sprite data to the surface pointer? If so it seems reduntant to have it as an object since it doesn't have a state.
Yes it was confusing and sounds like your over complicating things there is even a better solution than the one CyberFox suggested, "Resource Acquisition Is Initialisation" (RAII), use a reference counted smart pointer such as boost's shared_ptr that lets you use custom deleters then all is taken care of:

#include <SDL.h>#include <boost/shared_ptr.hpp>typedef boost::shared_ptr<SDL_Surface> surface_ptr;surface_ptr create_surface(const char* filename) {   return surface_ptr(SDL_LoadBMP(filename), SDL_FreeSurface);}//....	surface_ptr s = create_surface("...");


i think that is what you where after.
Might want to display some code and explain more so we understand your problem.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                          
Looking for video game music? Check out some of my samples at http://www.youtube.c...ser/cminortunes            
                                                          
I'm currently looking to create music for a project, if you are interested e-mail me at cminortunes@gmail.com    
                                                          
Please only message me for hobby projects, I am not looking to create music for anything serious.
OK, it works fine like this:

void GameLoop(){SpriteManager Sprite("data/sprite.bmp",WManager.GameWindow); //Overloaded constructor creates instance of SpriteManager class called "Sprite",//with the filepath and the surface to which it will be blitted as arguments //(GameWindow is included within the separate WManager instance of the //WindowManager class)Sprite.DrawSprite();SDL_Flip(WManager.GameWindow);}void CloseProgram(){Sprite.Free(); //Function to free up "Sprite"'s surface and clean up// It can't be seen by this function because the original constructor was defined locally earlier on// Leads to Sprite being an undeclared identifier - code won't compile}


What I would like to be able to do is this:

SpriteManager Sprite("data/sprite.bmp",WManager.GameWindow); //Declared like a global variable so that all functions can use itvoid GameLoop(){Sprite.DrawSprite();SDL_Flip(WManager.GameWindow);}void CloseProgram(){Sprite.Free();atexit(SDL_Quit);// etc.}


When I declare the constructor globally like that, it compiles without errors, but the sprite doesn't appear on screen when I run the program.

Hope that helps you further understand the problem.
One solution would be to create an Initialize function in your sprite class, then also have on OpenProgram() function.

ie.
SpriteManager Sprite; //Declared like a global variable so that all functions can use itvoid OpenProgram(){   Sprite.Initialize("data/sprite.bmp",WManager.GameWindow);}void GameLoop(){   Sprite.DrawSprite();   SDL_Flip(WManager.GameWindow);}void CloseProgram(){   Sprite.Free();   atexit(SDL_Quit);   // etc.}
Im not 100% sure on this from the code that uve posted but is:
WManager.GameWindow
set up where u are trying to use it in the second example?

to achieve what ur trying to do is this any better:

SpriteManager *Sprite; //Declared like a global variable so that all functions can use itvoid GameLoop(){Sprite = new SpriteManager("data/sprite.bmp",WManager.GameWindow);Sprite->DrawSprite();SDL_Flip(WManager.GameWindow);}void CloseProgram(){Sprite->Free();atexit(SDL_Quit);// etc.}
Perhaps make SpriteManager a singleton? Note that singletons share all the design problems that globals do [smile]

class SpriteManager {     static SpriteManager* singleton;     // ... all your normal code ...     // have a public static method to get the singleton instancepublic:     static SpriteManager& get_instance() { return *singleton; }};// preferably in the cpp file:SpriteManager* singleton = new SpriteManager(); // if possible// if not, provide a static init method you have to call eventually// now, change you init and deinit functions accordinly:void OpenProgram() { SpriteManager::get_instance().Initialize(...); }void GameLoop() { /* include all normal code */ SpriteManager::get_instance().DrawSprite(); }void CloseProgram() { SpriteManager::get_instance().Free(); /* do everything else */ }


Edit: deriving SpriteManager from boost::noncopyable (found in boost/utility.hpp) will further enforce the singleton semantics, but still not totally.

[Edited by - nilkn on June 16, 2005 10:04:46 PM]

This topic is closed to new replies.

Advertisement