对象删除自身并没有错。您必须简单地告诉窗口管理器从它的集合中删除该窗口,然后再删除。如果您让窗口管理器删除窗口对象,那就更好了。
如果你真的想避免这种行为,你可以在bool dead;
每个初始化为false
. 当要关闭窗口时,设置this->dead = true;
. 每一帧,让窗口管理器遍历它的窗口并删除那些死掉的窗口。
请注意,此解决方案仍然无法修复引用已删除窗口的外部系统引起的错误,但它确实具有集中删除窗口的优势。
我设计了很多游戏的窗口系统,根据我的经验,允许窗口删除自己是一个非常优雅的解决方案,即使它更容易出错。
一个最小的例子:
class Window
{
public:
void keyPressCallback(int c)
{
if (c == KEY_ESC)
{
manager.destroy(this);
return;
}
}
WindowManager& manager;
};
class WindowManager
{
public:
void destroy(Window* target)
{
delete target;
windows.erase(std::find(windows.begin(), windows.end(), target));
}
std::vector<Window*> windows;
};
只要没有指向该窗口的剩余指针,此方法就完全安全且语义健全。当窗口收到关闭信号时,它会自行关闭。
dead
带有标志的相同示例:
class Window
{
public:
Window() : dead(false) {}
void keyPressCallback(int c)
{
if (c == KEY_ESC)
{
dead = true;
return;
}
}
bool dead;
};
class WindowManager
{
public:
void cleanup()
{
for (auto iter = windows.begin(); iter != windows.end(); ++iter)
{
if (iter->dead) windows.erase(iter);
}
}
std::vector<Window*> windows;
};