C++ 在堆栈C+;上创建的对象中的数据无效+;

C++ 在堆栈C+;上创建的对象中的数据无效+;,c++,oop,pointers,stack,heap,C++,Oop,Pointers,Stack,Heap,对于这个问题,我真的找不到更好的标题了 我有三个类:复选框,按钮和背景 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, in

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

我有三个类:
复选框
按钮
背景

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);
}
class复选框:公共组件
{
私人:
按钮m_按钮;
公众:
复选框(常量点和位置、整数宽度、整数高度、标准::字符串文本);
复选框();
};
复选框::复选框(常量点和位置、整数宽度、整数高度、字符串文本):
组件(位置、宽度、高度),
m_按钮(按钮(点(宽-高,0)、新背景(“按钮”bg_sample.png,true)、新背景(“按钮”bg_onclick_sample.png,true)、高度、高度,10“),
{
}
类按钮:公共组件
{
私人:
std::字符串m_文本;
背景*m_p背景;
背景*m_pBackgroundOnClick;
int m_fontSize;
公众:
按钮(常量点和位置、背景*pBg、背景*pBg单击、整数宽度、整数高度、整数字体大小、标准::字符串标题);
~Button();
};
按钮::按钮(常量点和位置、背景*pBg、背景*pBg单击、整数宽度、整数高度、整数字体大小、字符串标题):
组件(位置、宽度、高度),
m_pBackground(pBg),
m_pBackgroundOnClick(pBgOnClick),
m_fontSize(fontSize),
m_文本(标题)
{
}
阶级背景
{
私人:
std::字符串m_pFileName;
布尔穆比林;
std::向量m_pImageData;
无符号整数m_宽度;
无符号整数m_高度;
胶状m_结构;
bool加载(const std::string和pFileName);
公众:
背景(const std::string和pFileName,bool bTiling);
~Background();
布尔图(常数点和位置、无符号整数宽度、无符号整数高度);
布尔图(常数点和位置);
};
背景::背景(常量字符串和pFileName,bool bTilling):
m_bTiling(bTiling),
m_pFileName(pFileName)
{
加载(pFileName);
}
如您所见,
复选框
类包括
按钮m_按钮
按钮
类包括
背景*m_pBg
。在
Background
构造函数中,我加载图像数据并将其存储在
std::vector
中,这并不重要-我知道它正在工作,因为它已经被检查过了

当我创建
复选框
对象时,它的
m_按钮
中的数据已损坏。当我试图在调试模式下检查图像数据内部的内容时,我得到的信息是图像数据是空的,背景文件名是
“读取字符串中的字符时出错”
。虽然当我看到在调试模式下一步一步地执行代码时,我已经看到数据被正确地加载到构造函数中,但是在创建对象时,数据已经损坏了

当我更改要在堆上创建的
CheckBox
类中的
m_按钮
字段时(指向
按钮
,使用
新建
操作符创建的对象),一切似乎都正常工作。数据正在正确加载并保持如下状态


有谁能解释一下造成这种问题的原因吗?

问题是你没有服从

class
按钮
管理内存本身,因此当您创建副本或进行分配时,您可能会遇到麻烦。我没有深入研究代码,所以不能肯定这是根源(尽管这是一个问题),但我非常肯定它是


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

您的
按钮
将被复制到
复选框的构造函数的初始化列表中的堆栈上

m_button = Button();
default=运算符正在做的是将新创建的
按钮
对象中的每个字段复制到
m_按钮

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;

两个指针现在都指向同一个对象!同样的事情也发生在你的
背景上*
。您有两个
按钮
s,它们指向内存中某个相同的
背景
对象。但是您在初始化列表中创建的第二个
按钮
正在被销毁,因为它超出了范围,并且很可能(因为我没有看到您的
按钮
类的析构函数)正在发生什么,您正在销毁
按钮
析构函数中的
背景
对象。这就是为什么在调试模式下跟踪代码时,您会看到正确创建的
背景
,但随后它会被
按钮
对象销毁。

您甚至没有提供所有代码,例如,~Button()破坏背景会怎么样?