[C++/SDL] private static vars?

Recommended Posts

homeboye    115
hey, i made a class with a private static variable SDL_Surface *image; and it is giving me troubles.
void CSDLmain::LoadIMG(char *image_path)
{
image = IMG_Load ( image_path );
//debug stuff, commented-out
}

void CSDLmain::BlitIMG(SDL_Surface *screenSurface, int x_pos, int y_pos)
{
SDL_Rect rcDest = { x_pos, y_pos, 0, 0 };
SDL_BlitSurface ( image, NULL, screenSurface, &rcDest );
SDL_FreeSurface ( image );
}


error: [Linker error] undefined reference to CSDLmain::image' P.S.: it's the same if i put in public, but.. it does work if i put it as a global var, but i do not want that.

Share on other sites
pulpfist    528
your static variable has to be both declared and initialized.
Im guessing you have not initialzed it.

Typically you have

class A
...
private:
static Surface srf; // declare the static variable
...

Surface A::srf = NULL; // the actual definition goes here (if you forget this you are likely to get a linker error like yours)

in the corresponding source file

[Edited by - pulpfist on May 17, 2006 2:52:29 PM]

Share on other sites
homeboye    115
so, this should be it then?
SDL_Surface CSDLmain::image = NULL;

main.cpp In function int SDL_main(int, char**)':
35 main.cpp conflicting declaration 'SDL_Surface CSDLmain::image'
23 SDLmain.h 'CSDLmain::image' has a previous declaration as SDL_Surface*CSDLmain::image'
35 main.cpp conversion from int' to non-scalar type SDL_Surface' requested

if i put a asterix after SDL_Surface it says it's redeclared and if i remove the SDL_Surface it says it's private and.. if i put the *image to public it says "undefined reference" again...

ty.

Share on other sites
pulpfist    528
You got something like this right?
class CSDLmain{private:    static SDL_Surface* image;};(If you dont have a CSTLmain.cpp file, make sure this next line is outside and after the class definition, and give your .h file inclusion guards, so that if you happen to include it several times you dont get the redeclared error)SDL_Surface* CSDLmain::image;

That should work.
The = NULL thing is not needed btw since initialization to zero is done atomatically for static member variables.

Share on other sites
Fruny    1658
Quote:
 Original post by pulpfistyour static variable has to be both declared and initialized.Im guessing you have not initialzed it.

Declared and defined.

A variable can be defined but uninitialized.

int i; is an example.

Share on other sites
pulpfist    528
Thanks fruny, I forgot to fix that mistake =)

Share on other sites
homeboye    115
i do have a CSDLmain.cpp file, tried it, didn't work :/
i had the inclusion guards from the get go.
and nope, still nothing, or should i say, the same.

Share on other sites
pulpfist    528
Hmm Im starting to wonder if you have included the CSDLmain.cpp file in your project correctly.
Are you getting similar errors for the GetIMG and BlitIMG functions too?

You got the line
#include "CSDLmain.h"
at the top of CSDLmain.cpp file?

If you have the exact same errors as you described earlier Im supprised indeed.
Sorry if I have confused you.
If you post the complete source code its easier to see if is a code problem or not...

Share on other sites
evillive2    779
The problem here is that you are using a static class member variable where I don't think you want to. Do a little research on static class member variables to see how they work.

(Just a general idea but could/should be worded better)
Static members are kind of like global variables inside the classes namespace in the way they do not belong to any single object but to the class itself.

For example:
class funky{public:    static int static_member;public:    int normal_member;//...};funky foo;foo.normal_member = 111; // a normal member variable                         // because this is a static member variablefoo.static_member = 666; // this should give your compile time errorfunky::static_member = 777; // this should be fine - notice no object is used

Static member variables have their use but I don't think it is what you want in this case as each time you load an image you will a)lose the original image and possibly b)leak memory.

Try taking the static part away and this should work fine.

 to get your code above working with a static member
// note it isn't in the constructor and looks like a global in C// with slightly different syntaxSDL_Surface *CSDLmain::image = NULL;void CSDLmain::LoadIMG(char *image_path){  CSDLmain::image = IMG_Load ( image_path );  //debug stuff, commented-out}void CSDLmain::BlitIMG(SDL_Surface *screenSurface, int x_pos, int y_pos){  SDL_Rect rcDest = { x_pos, y_pos, 0, 0 };  SDL_BlitSurface ( CSDLmain::image, NULL, screenSurface, &rcDest );  SDL_FreeSurface ( CSDLmain::image );}

Share on other sites
yes, I think evillive2 is right. I would try that, and if that dosen't work, then you might want to post more code.

Share on other sites
yes, I think evillive2 is right. I would try that, and if that dosen't work, then you might want to post more code.

EDIT: Also, in your BlitIMG code, why do you want to free the surface everytime you blit it the screen? To me, that makes no since, unless I am just being stupid and missing something...?

Share on other sites
evillive2    779
Quote:
 Original post by Chad SmithEDIT: Also, in your BlitIMG code, why do you want to free the surface everytime you blit it the screen? To me, that makes no since, unless I am just being stupid and missing something...?

Chad is right about the freeing the surface part. If you make CSDLmain::image a regular member variable you can free it up in the destructor to make sure it is always freed when you no longer need the CSDLmain object it belongs to.

In general you should load your images once before they are needed and free them once when they are no longer needed.

Check out lazy foo's SDL tutorials for some insight as to how to use SDL. I think they are great for beginners because they are basic and really push the basics without getting too far off track.

You might also want to look at cone3d. A little older and not quite the best solutions (although no tutorial really is) it still provides a decent background for making games with SDL.

Hope it helps.

Share on other sites
// SDLmain.h//class SDLmain{public:  SDLmain();  ~SDLmain();  static void LoadIMG(char*);  static void BlitIMG(SDL_Surface*, int, int);private:  static SDL_Surface* image;};// SDLmain.cpp//#include "SDLmain.h"SDL_Surface* SDLmain::image;// Rest of code////

But I would suggest as evillive2 and Chad have pointed out and make image an object variable rather than a class variable because then it is easy to perform the cleanup in the destructor. Doing it this way, you can load the image once and blit multiple times (as you may need to if part of the background becomes obscured and visible again)

Your BlitImage function shouldn't have to worry about memory management (although I can see why you did this because where else would you free the surface without it becoming an ugly hack) but you understand that this image can only be blitted once until you load the image again.

Share on other sites
// SDLmain.h//class SDLmain{public:  SDLmain();  ~SDLmain();  static void LoadIMG(char*);  static void BlitIMG(SDL_Surface*, int, int);private:  static SDL_Surface* image;};// SDLmain.cpp//#include "SDLmain.h"SDL_Surface* SDLmain::image;// Rest of code////`

But I would suggest as evillive2 and Chad have pointed out and make image an object variable rather than a class variable because then it is easy to perform the cleanup in the destructor. Doing it this way, you can load the image once and blit multiple times (as you may need to if part of the background becomes obscured and visible again)

Your BlitImage function shouldn't have to worry about memory management (although I can see why you did this because where else would you free the surface without it becoming an ugly hack) but you understand that this image can only be blitted once until you load the image again.

Create an account

Register a new account