我认为我必须在这里“做错事”。我有一个使用gtkmm的程序。该程序的主窗口是Gtk::Window
的子类,我在Glade中提取了应用程序的基础。
这是主窗口构造函数的编辑版本:
template<class T>
static T*
get_widget (Glib::RefPtr<Gtk::Builder> builder, const Glib::ustring& name)
{
T* widget;
builder->get_widget (name, widget);
if (! widget) no_such_widget (name);
return widget;
}
app_window::app_window ()
{
Glib::RefPtr<Gtk::Builder> builder;
try {
builder = Gtk::Builder::create_from_file (installed_ui_name);
}
catch (const Glib::FileError& err) {
g_error ("Couldn't open UI definition file at %s",
installed_ui_name);
throw;
}
// main_box is a std::unique_ptr<Gtk::Widget>, a field of app_window.
//
// This works fine: the Gtk::Box gets added as the main child of this
// app_window and survives until the app_window is destroyed.
main_box.reset (get_widget <Gtk::Box> (builder, "main-box"));
add (* main_box);
auto accel_group = get_accel_group ();
// This doesn't work so well
//
// menu_quit is a Gtk::MenuItem*. The object seems to be actually
// constructed for the call to builder->get_widget, because its existence
// stops the menu item from being finalized at the end of the application.
auto menu_quit (get_widget<Gtk::MenuItem> (builder, "menu-quit"));
menu_quit->add_accelerator ("activate", accel_group,
GDK_KEY_q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
using std::bind;
menu_quit->signal_activate ().connect (bind (& app_window::on_close, this));
show ();
}
设置窗口时,我想为菜单项等注册各种信号处理程序。(示例中的menu_quit
小部件只是其中之一)。为此,我想我需要使用builder->get_widget()
来获取要讨论的对象。
问题是我现在有一个({1}}的子类的实例,我不知道如何处理它。如果我在指针上调用delete,则小部件不会出现在应用程序中,但不会发生其他问题。这有点令人困惑:我希望无效或分段错误(取决于是否有其他人认为它拥有该对象)。
另一方面,如果我泄漏了指针,假设该对象将被添加了main_box的容器所拥有,则会出现内存泄漏。特别是,Gtk::Widget
的基础menu_quit
未完成,因为引用计数太高。 (我可以用GDB轻松检查)
“解决方案”是将gtk_image_menu_item
作为builder->get_widget
中的字段存储到每个对象的指针,然后在析构函数中将其删除(使用app_window
自动删除或std::auto_ptr
)。但那太可怕了:我不想为每一个菜单项写出一个字段!避免这种废话是首先使用std::unique_ptr
的重点!
假设这不是一个错误(gtkmm 3.12.0,如果这是相关的),我认为我只是做错了。应用程序应该如何执行此操作?