如果 QMenu 是 unique_ptr,为啥 QAction 不添加到 QMenu?
Posted
技术标签:
【中文标题】如果 QMenu 是 unique_ptr,为啥 QAction 不添加到 QMenu?【英文标题】:Why QAction is not adding to QMenu, if QMenu is unique_ptr?如果 QMenu 是 unique_ptr,为什么 QAction 不添加到 QMenu? 【发布时间】:2015-06-14 18:31:43 【问题描述】:代码示例:
auto fileMenu = std::make_unique<QMenu>(this->menuBar()->addMenu("First"));
fileMenu->addAction("AFirst");
auto x = this->menuBar()->addMenu("Second");
x->addAction("ASecond");
结果:
我在菜单栏中有 2 个菜单,但在第一个菜单中 - 出于某种原因,没有任何操作。第二个菜单正确有动作。
我尝试了不同的方法,例如类成员指针等,但这是可能的最短示例 - 如果 QMenu 是 unique_ptr,则缺少 QAction。谁能为我解释一下?父窗口是QMainWindow,以防万一。
系统信息: Win8.1 x64,编译器为VS2013,Qt 5.4 x32。
【问题讨论】:
嗯。我希望使用 std::unique_ptr 导致双重删除,因为当父级超出范围时 Qt 将删除子级。 您不应该将QMenu
包裹在unique_ptr
中;它已经由菜单栏管理。
QAction 没有被包裹,QMenu 被包裹在这里。
抱歉,已更正。我正在查看文档中addMenu
的另一个重载,即返回QAction
。
您的 std::unique_ptr 文件菜单是否超出范围?也许您的 fileMenu 已经被释放但仍连接到父级并且您正在体验 UB。
【参考方案1】:
在这一行:
auto fileMenu = std::make_unique<QMenu>(this->menuBar()->addMenu("First"));
fileMenu
成为一个新的QMenu
对象(使用this constructor)。完全一样:
std::unique_ptr<QMenu> fileMenu(new QMenu(this->menuBar()->addMenu("First")));
然后,您将QAction
添加到这个临时的新菜单中。
第二种情况:
auto x = this->menuBar()->addMenu("Second");
x->addAction("ASecond");
x
成为指向现有菜单的指针。这就是区别。
无论如何,通常你不应该使用std::unique_ptr
持有QObject
s。在 Qt 中,有一个约定,您可以通过将父级分配给每个 QObject
s 来形成一棵树。父级递归删除其子级,您不应手动管理它们,否则在某些特定情况下可能会导致双重释放。
【讨论】:
不过,您并没有解释为什么第一种方法不起作用而第二种方法起作用...... @peppe:“然后,向这个临时的新菜单添加一个 QAction。”将 QAction 插入到临时对象并不会将其插入到menuBar
,这不是很明显吗?
嗯,这不完全是“临时的”。 QMenuBar::addMenu
将创建一个新的 QMenu
作为孩子,并将其返回。那么真正的问题是unique_ptr
将在fileMenu
超出范围时破坏QMenu
。 OP还说“试图让uniqueptr成为classmember,所以,它不会超出范围-结果是一样的”,但我还没有看到更新的代码。
@peppe:好的,这不是 C++ 意义上的“临时”。它只是一个新对象,不是子菜单。它是QMenu
返回的子 QMenuBar::addMenu
。看来,简单地创建一个 QMenu
并以另一个 QMenu
作为父级并不能使其成为子菜单。即使没有使用 unique_ptr
进行管理,它也不会按预期工作。以上是关于如果 QMenu 是 unique_ptr,为啥 QAction 不添加到 QMenu?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 QMenu:hover 在 Qt Designer 中不起作用
为啥我不能在 C++14 的 lambda 中移动 std::unique_ptr?
当我以 root 身份运行 PyQt 应用程序时,为啥我的 QMenu 中不显示 QIcons?