Pergunta

I couldn't really find any better title for this question.

I have three classes: CheckBox, Button and Background.

class CheckBox : public Component
{
private:
    Button m_button;
public:
    CheckBox(const Point &pos, int width, int height, std::string text);
    CheckBox();
};

CheckBox::CheckBox(const Point &pos, int width, int height, string text) : 
    Component(pos, width, height),
    m_button(Button(Point(width-height,0), new Background("button_bg_sample.png", true), new Background("button_bg_onclick_sample.png", true), height, height, 10, "")),
{

}


class Button : public Component
{
private:
    std::string m_text;
    Background* m_pBackground;
    Background* m_pBackgroundOnClick;
    int m_fontSize;
public:
    Button(const Point& pos, Background* pBg, Background* pBgOnClick, int width, int height, int fontSize, std::string title);
    ~Button();

};

Button::Button(const Point& pos, Background* pBg, Background* pBgOnClick, int width, int height, int fontSize, string title) : 
    Component(pos, width, height), 
    m_pBackground(pBg),
    m_pBackgroundOnClick(pBgOnClick),
    m_fontSize(fontSize),
    m_text(title)
{
}


class Background
{
private:
    std::string m_pFileName;
    bool m_bTiling;
    std::vector<unsigned char> m_pImageData;
    unsigned int m_width;
    unsigned int m_height;
    GLuint m_texture; 

    bool load(const std::string& pFileName);
public:
    Background(const std::string& pFileName, bool bTiling);
    ~Background();

    bool draw(const Point &pos, unsigned int width, unsigned int height);
    bool draw(const Point &pos);
};

Background::Background(const string& pFileName, bool bTiling) : 
    m_bTiling(bTiling), 
    m_pFileName(pFileName)
{
    load(pFileName);
}

So as you can see, CheckBox class includes Button m_button and Button class includes Background* m_pBg. In Background constructor I load image data and store it in std::vector, it doesn't really matter - I know it's working, because it was already checked.

When I create CheckBox object, the data inside it's m_button is corrupted. When I try to check what's inside image data in debug mode, I get information that it's empty and the file name of that background is "Error reading characters in string". Though when I saw following step by step the code in debug mode, I've seen that the data was properly loaded inside constructor, but somehow when the object was created, data was already corrupted.

When I changed m_button field in CheckBox class to be created on a heap (pointer to Button, object created by using new operator) everything seems to be working just fine. Data is being loaded properly and remains like this.

Could anyone please explain me what can be the reason of such problem?

Foi útil?

Solução 2

Your Button which is created on stack in initialization list of CheckBox's constructor is being copied to m_button field:

m_button = Button();

What default =operator is doing, is COPYING every field inside new created Button object to m_button:

m_button.height = b.height // Let's assume, that 'b' is the name of this new Button
m_button.width = b.width
m_button.name = b.name
...

Now what happens if you have a pointer p1 which points to some object and you have the other pointer p2 and you assign p1 to p2?

int* p1 = new int(5);
int* p2 = p1;

Both pointers are now pointing to the same object! And the same thing happend to your Background*. You have two Buttons which point to the same Background object somewhere in memory. But your second Button created in initializing list is being destroyed as it goes out of a scope and what PROBABLY (because I haven't seen destructor of your Button class) is happening, you are destroying the Background object in your Button destructor. That's why when you follow the code in debug mode you see properly created Background, but later it is being destroyed with the Button object.

Outras dicas

The problem is that you're not obeying the rule of three.

The class Button manages memory itself, so when you create copies or make assignments, you'll likely run into trouble. I didn't dig in the code so can't say for sure this is the root (it is a problem nonetheless), but I'm pretty sure it is.

This could all be avoided if you used smart pointers instead of raw pointers to manage resources.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top