Jump to content
  • Advertisement
Sign in to follow this  
ukdeveloper

Problems calling constructor

This topic is 4877 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 it

void 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.

Share this post


Link to post
Share on other sites
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 it

void OpenProgram()
{
Sprite.Initialize("data/sprite.bmp",WManager.GameWindow);
}

void GameLoop()
{


Sprite.DrawSprite();

SDL_Flip(WManager.GameWindow);

}

void CloseProgram()
{

Sprite.Free();

atexit(SDL_Quit);

// etc.
}

Share this post


Link to post
Share on other sites
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 it

void GameLoop()
{

Sprite = new SpriteManager("data/sprite.bmp",WManager.GameWindow);
Sprite->DrawSprite();

SDL_Flip(WManager.GameWindow);

}

void CloseProgram()
{

Sprite->Free();

atexit(SDL_Quit);

// etc.
}

Share this post


Link to post
Share on other sites
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 instance
public:
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]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!