SDL and Copy Constructors

Started by
14 comments, last by yet_another_painter 10 years, 4 months ago

So I've been wrestling with this problem for a few days now. So I have a entity class and I thought I would use a vector to make it so i could have a dynamic array of the entity's. It crashed horribly and i learned that in my SmartImage class (located inside the entity class) was only making a shallow copy. So i'm trying to make a deep copy using the copy constructor. My program compiles but it crashes as soon as it launches. It seems even initializing the SmartImage class will cause it to crash. What am i doing wrong?

SmartImage.h


class SmartImage
{
    private:
            bool image_loaded;
    public:
           SmartImage();
           ~SmartImage();
           // copy constructor:
           SmartImage (const SmartImage& param);
           
           SDL_Surface *surface;
           void load(std::string filename);
           void copy_surface(SDL_Surface *target_surface);
};
#include"SmartImage.cpp"

SmartImage.cpp


SmartImage::SmartImage()
{
 surface=NULL;
 image_loaded = false;     
}

SmartImage::~SmartImage()
{
 SDL_FreeSurface(surface);      
}

// copy constructor
SmartImage::SmartImage (const SmartImage& param)
{         
 surface = SDL_DisplayFormat(param.surface);          
}

void SmartImage::load(std::string filename)
{
    if(image_loaded == false)
    {
     surface = load_image(filename);
     image_loaded = true;
    }    
    else
    {
     SDL_FreeSurface(surface);
     surface = load_image(filename);
    }  
}

void SmartImage::copy_surface(SDL_Surface *temp_surface)
{
     if(image_loaded == true)
     {
      SDL_FreeSurface(surface);               
     }
 surface = SDL_DisplayFormat(temp_surface); 
 image_loaded = true;     
}
Advertisement

Do you know about the rule of three? It looks like you didn't define an operator=, so you probably don't. Read about it and you may have an easier time understanding your problem.

I know of the rule of three but i'm having trouble implementing it. I'm looking at a tutorial and trying to implement the copy constructor,copy assignment operator, and the destructor. This is what i'm looking at http://www.cplusplus.com/doc/tutorial/classes2/ and i'm about half way down the page.

Modified the .h to try and include the assignment operator. It more matches what the tutorial has but I don't think it's going to do what i want. I don't exactly understand how to use the assignment operator tho. Still crashes when I try to make a SmartImage object which means something is majorly wrong right?


class SmartImage
{
    private:
            bool image_loaded;
            
    public:
           SmartImage();
           ~SmartImage();
           // copy constructor:
           SmartImage (const SmartImage& param) : surface(new SDL_Surface(param.content())) {}
           //access content
           const SDL_Surface& content() const {return *surface;}
           SDL_Surface *surface;
           void load(std::string filename);
           void copy_surface(SDL_Surface *target_surface);
};

#include"SmartImage.cpp"

the .cpp


SmartImage::SmartImage()
{
 surface=NULL;
 image_loaded = false;     
}

SmartImage::~SmartImage()
{
 SDL_FreeSurface(surface);      
}

void SmartImage::load(std::string filename)
{
    if(image_loaded == false)
    {
     surface = load_image(filename);
     image_loaded = true;
    }    
    else
    {
     SDL_FreeSurface(surface);
     surface = load_image(filename);
    }  
}

void SmartImage::copy_surface(SDL_Surface *temp_surface)
{
     if(image_loaded == true)
     {
      SDL_FreeSurface(surface);               
     }
 surface = SDL_DisplayFormat(temp_surface); 
 image_loaded = true;     
}

You should check if SDL_DisplayFormat return NULL is that the case perhaps there is your error because should a other function need to access your surface but found only NULL could cause your problem. you should in general check if got SDL_Surface notequal NULL from the SDL functions.

The constructor function is called as soon as that object is created, so depending on where your object is created, this may occur before the SDL_Init of your program is even called. Depending on how you've set up your program, your constructor may be calling an SDL function before SDL has been initialized, which may be the source of your problem.

Edited for clarification due to a miswording.

#include"SmartImage.cpp"

What is that?

The constructor function is called as soon as that object is created, so if your object is not dynamically allocated to memory during run time this will be before the main function of your program is even called. Depending on how you've set up your program, your constructor may be calling an SDL function before SDL has been initialized.

OMG I had no idea that copy constructor would run before main. I changed it to a pointer and now use the new keyword when I get into main. It stopped the crashing and after a few more hours of poking around I got it to work how I wanted to. So thank you, I feel like I need to research pointers more. I get the concept behind them but actually using them is giving me trouble. It seems I only run into problems with SDL_Surface tho.


#include"SmartImage.cpp"

What is that?

It's the .cpp file to the .h I don't see a problem with that line of code. I also listed the .cpp in my posts soooooooo what's up?


#include"SmartImage.cpp"

What is that?

It's the .cpp file to the .h I don't see a problem with that line of code. I also listed the .cpp in my posts soooooooo what's up?

The problem is that you cannot use your SmartImage header in two or more files across your project. Each time you include SmartImage.h, it will also include SmartImage.cpp and all its definitions. If you include SmartImage.h in more than one file in your project, you will consequently have more than one definition of each of the class member functions and the linker will fail to do its job.

Add the file SmartImage.cpp to your project instead and compile it as a separate function. And, as the file is shown at the moment, it has to include the necessary headers as well in order to compile properly.

Is it common practice to include the header file more then once? In my main file i just have .h after .h listed. I always thought this way was better since I used to do it like

a.h

a.cpp

b.h

b.cpp

c.h

c.cpp

Now a days I do

a.h

b.h

c.h

with the .cpp included from the .h


OMG I had no idea that copy constructor would run before main. I changed it to a pointer and now use the new keyword when I get into main. It stopped the crashing and after a few more hours of poking around I got it to work how I wanted to. So thank you, I feel like I need to research pointers more. I get the concept behind them but actually using them is giving me trouble. It seems I only run into problems with SDL_Surface tho.

Just some advice, I recommend avoiding any use of SDL functions within constructors or destructors (the same issue will occur if you quit SDL before your destructors are called when the program closes). Simply create an initializing function and a clean up function which fulfill the same purpose that your constructors and destructors do now. Call the initializing function after you initialize SDL and before your game loop, and call the clean up function after your game loop and before you call SDL_Quit();

This way you can avoid needing to dynamically allocate your object after initializing SDL. You should avoid dynamically allocating anything unless it's absolutely required.

This topic is closed to new replies.

Advertisement