1

对于这个问题,我真的找不到更好的标题。

我有三个类CheckBoxButtonBackground

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);
}

如您所见,CheckBox类包括Button m_buttonButton类包括Background* m_pBg。在Background构造函数中,我加载图像数据并将其存储在 中std::vector,这并不重要 - 我知道它正在工作,因为它已经被检查过。

当我创建CheckBox对象时,其中的数据m_button已损坏。当我尝试在调试模式下检查图像数据中的内容时,我得到的信息是它是空的,并且该背景的文件名是"Error reading characters in string". 虽然当我在调试模式下逐步看到代码时,我已经看到数据已在构造函数中正确加载,但不知何故,当创建对象时,数据已经损坏。

当我将类中的m_button字段更改CheckBox为在堆上创建时(指针Button,使用new运算符创建的对象),一切似乎都工作得很好。数据正在正确加载并保持这种状态。

谁能解释一下这个问题的原因是什么?

4

2 回答 2

2

问题是你没有遵守三的规则

班级Button自己管理记忆,因此当您创建副本或分配作业时,您可能会遇到麻烦。我没有深入研究代码,所以不能确定这是根源(尽管如此,这是一个问题),但我很确定它是。

如果您使用智能指针而不是原始指针来管理资源,这一切都可以避免。

于 2012-11-19T16:21:47.847 回答
1

您在构造函数Button的初始化列表中的堆栈上创建CheckBox的内容被复制到m_button字段:

m_button = Button();

默认 =operator 正在做的是将新创建Button的对象中的每个字段复制到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
...

现在,如果您有一个指向p1某个对象的指针并且您有另一个指针p2并分配给p1会发生p2什么?

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

两个指针现在都指向同一个对象!同样的事情也发生在你的Background*. 您有两个Buttons 指向Background内存中某处的同一个对象。但是您Button在初始化列表中创建的第二个正在被破坏,因为它超出了范围,并且可能(因为我没有看到您的Button类的析构函数)正在发生什么,您正在破坏析构函数Background中的对象Button。这就是为什么当您在调试模式下跟踪代码时,您会看到正确创建Background的,但后来它被Button对象破坏了。

于 2012-11-20T14:14:44.513 回答