【问题标题】: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。

标签: c++ qt


【解决方案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 持有QObjects。在 Qt 中,有一个约定,您可以通过将父级分配给每个 QObjects 来形成一棵树。父级递归删除其子级,您不应手动管理它们,否则在某些特定情况下可能会导致双重释放。

【讨论】:

  • 不过,您并没有解释为什么第一种方法不起作用而第二种方法起作用......
  • @peppe:“然后,向这个临时的新菜单添加一个 QAction。”将 QAction 插入到临时对象并不会将其插入到menuBar,这不是很明显吗?
  • 嗯,这不完全是“临时的”。 QMenuBar::addMenu 将创建一个新的 QMenu 作为孩子,并将其返回。那么真正的问题是unique_ptr 将在fileMenu 超出范围时破坏QMenu。 OP还说“试图让uniqueptr成为classmember,所以,它不会超出范围-结果是一样的”,但我还没有看到更新的代码。
  • @peppe:好的,这不是 C++ 意义上的“临时”。它只是一个新对象,不是子菜单。它是QMenu 返回的 QMenuBar::addMenu。看来,简单地创建一个 QMenu 并以另一个 QMenu 作为父级并不能使其成为子菜单。即使没有使用 unique_ptr 进行管理,它也不会按预期工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
相关资源
最近更新 更多