gpt4 book ai didi

c++ - QObject::connect 函数中的 QObject* 上下文

转载 作者:可可西里 更新时间:2023-11-01 14:56:51 27 4
gpt4 key购买 nike

我读过 documentation对于 QObject::connect(对于 Qt 5.4),但我对重载有疑问

QMetaObject::Connection QObject::connect(const QObject * sender, PointerToMemberFunction signal, const QObject * context, Functor functor, Qt::ConnectionType type = Qt::AutoConnection)

context 参数到底是什么?它的目的是什么?它可以用于在线程中的本地事件循环中建立连接吗?

有人可以提供示例说明如何/何时使用此重载(当上下文不是 this 时)吗?

最佳答案

上下文对象在两种情况下使用。

自动断开

让我们先退一步问问自己:Qt 什么时候断开连接?

使用通常的connect(sender, signal, receiver, slot) 连接,存在三种可能性:

  1. 当有人明确调用disconnect时;
  2. sender被删除时;
  3. receiver被删除时。

特别是在#2 和#3 的情况下,Qt 那样做是有意义的(实际上,它必须那样做,否则你会发生资源泄漏和/或崩溃) .


现在:当使用 connect 重载获取仿函数时,Qt 何时断开连接?

请注意,如果没有 context 参数,则只涉及一个 QObject:发送者。因此答案是:

  1. 当有人明确调用disconnect时;
  2. sender被删除时。

当然,这里没有接收者对象!因此只有发送方自动控制连接的生命周期。

现在,问题是仿函数可能会捕获一些可能变得无效的额外状态,在这种情况下希望连接自动断开。典型案例是 lambda:

connect(sender, &Sender::signal, 
[&object1, &object2](Param p)
{
use(object1, object2, p);
}
);

如果 object1object2 被删除会怎样?连接仍将存在,因此发出信号仍将调用 lambda,后者将访问已销毁的对象。这有点糟糕......


出于这个原因,当涉及到仿函数时,引入了采用上下文对象connect 重载。使用该重载建立的连接也将自动断开连接

  1. context 对象被删除时。

你可能是对的,你会多次看到仿函数中使用的相同“主”对象,例如

connect(button, 
&QPushButton::clicked,
otherWidget,
[otherWidget]()
{
otherWidget->doThis(); otherWidget->doThat();
}
);

这只是 Qt 中的一种模式——在为子对象设置连接时,您通常将它们连接到 this 对象上的插槽,因此 this 可能是最共同的背景。然而,一般来说,你也可能会得到类似的结果

// manages the lifetime of the resources; they will never outlive this object
struct ResourceManager : QObject
{
Resource res1; // non-QObjects
OtherResource res2;
};

ResourceManager manager;
connect(sender, signal, manager, [&manager](){ use(manager.res1, ...); });
// or, directly capture the resources, not the handle

因此,您正在捕获 manager 的部分状态。


在最一般的情况下,当没有可用的context对象时,如果lambda捕获的对象有可能在连接中存活下来,那么你必须通过弱指针捕获它们,并尝试在尝试访问它们之前将这些指针锁定在 lambda 中。

在特定线程/事件循环中运行仿函数

很快:当指定上下文对象时,仿函数将运行到上下文的线程中,就像使用接收者对象的普通连接一样。事实上,请注意,采用上下文的 connect 重载采用连接类型(而没有上下文的不采用连接类型——连接始终是直接的)。

同样,这很有用,因为 QObject 不是可重入的或线程安全的,您必须仅在它所在的线程中使用 QObject。如果您的仿函数访问另一个线程中的对象,则它必须在该线程中执行;将该对象指定为上下文可以解决问题。

关于c++ - QObject::connect 函数中的 QObject* 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27952902/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com