繁体   English   中英

Qt信号:将动态分配的参数的所有权传递给插槽?

[英]Qt Signals: Passing ownership of dynamically allocated argument to a slot?

我不知道如何准确地称呼这个问题,所以这里是解释:

我有一个自定义小部件,当完成编辑后,该小部件会发出一个带有根据用户输入构建的自定义对象的信号,例如

void GGActionEditor::finishEditing() {
  GGAction act;
  // Set up according to user input
  emit actionChanged(act);
}

在此代码中,连接到单个对象的接收器可以存储该对象的副本或以任何合适的方式对其进行处理,而小部件可以忽略它。

但是,当小部件可以通过类层次结构构建不同类型的对象时,如何处理这种情况呢? 喜欢:

void GGActionEditor::finishEditing() {
  GGAction *pAct;
  // Create and set up according to user input, e.g.
  if (...) pAct = new GGSpecialAction;
  else pAct = new SimpleAction;
  emit actionChanged(pAct);
}

在这种情况下处理对象生命周期的最佳解决方案是什么? 小部件无法知道是否有任何接收者接管了Action对象。 同样,如果连接了多个接收器,它们都不知道是否有另一个对象接管了该参数...
在“最佳”情况下,这可能会导致泄漏; 但是也会导致该参数被多次删除。

更新:
有关我的实际情况的更多信息,但是,我也对常规解决方案感兴趣:

传递的对象将由接收器存储,并保留在应用程序的域模型中。 该模型将负责以后删除它。
简单的解决方案是像上述“简单的”按值情况一样处理这种情况。 但是,如果根本没有连接任何接收器,则该物体会泄漏; 并且没有100%保证只有1个接收者会这样做(在我的实际应用逻辑中会是这种情况,但是既不能检查也不能以这种方式执行)。

我想出了一些可能的解决方案,并对任何评论或补充内容感兴趣:

  1. 只是希望它能解决
    假设将有1个接收器来接管该参数。 这可能适合我的应用程序,但我对此不满意
  2. 使用共享指针
    正如Eugene在回答中所说,shared_ptr(或QSharedPointer)将简化这一过程。 任何接收者和发送者都将使用共享的指针,因此生命周期是自动管理的。 但这迫使我的域模型也为持有此类Action对象的每个类使用共享指针。 这不太适合我的模型,因为这些类应该汇总操作。 共享指针不适用于持有对“属于”该对象的对象的引用。
  3. 添加指示超车的参数
    在信号中添加bool* ,以指示是否有接收者接管了该操作。 接收者知道,如果该值为真,它将无法再超过它。 此外,如果没有接收者接收,则发送方知道是否应删除该对象。 但是,哪个接收者以先到先得的方式获取对象是非常随机的。 而且它污染了界面...
  4. 对不同的具体类别使用不同的信号
    在这种情况下,接收方的插槽可以知道使用了哪个具体子类并制作了该对象的副本。 但是,这为使用类层次结构可以很好地完成的事情添加了额外的信号/插槽。此外,每个子类都必须有一个复制控制器。
  5. 向类添加一个clone方法
    与上述类似,但只有1个信号。 多态clone将创建具体子类的副本。
  6. 使用专用接口代替信号/插槽
    做一个GGIActionReceiver类,并在指定最多1个实例GGActionEditor 该实例是接管Action对象的唯一合格对象。 仍然可以发信号通知其他人,但是他们一定不能超越指针。 这样,发送者还知道是否必须删除对象(未设置接收者)

这里的一种选择是通过std :: shared_ptr <>或其他一些引用计数机制来使用共享所有权。 这样,只要有人需要,该对象就可以生存。

Qt的正常所有权模型不太有效,因为您无法确定有多少个信号用户希望拥有同一对象的所有权。

取决于您的逻辑,共享所有权可能导致闭环,并打破闭环,您可能被迫在一个或两个抽象中打洞。

确保不要将Qt所有权与shared_ptr混合使用-您的QObject不能有父级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM