请考虑以下代码
class A : public QWidget
{
signals:
void readyToBeClosed();
protected:
void closeEvent(QCloseEvent* e)
{
QWidget::closeEvent(e);
emit readyToBeClosed();
}
}
class B: public QWidget
{
public:
B(A* obj)
{
connect(obj,SIGNAL(readyToBeCLosed()),this,SLOT(cleanUp());
}
private slots:
void cleanUp()
{
//DO SOMETHING
}
}
安全吗?我冒险崩溃导致对象obj在发出信号之后和cleanUp函数返回之前被销毁了吗?
非常感谢。
答案 0 :(得分:3)
这是因为信号/槽系统的功能类似于函数调用(添加了“连接”机制),如the Qt Documentation about Signals and Slots中所述。
当您发出信号时,将调用连接到它的所有插槽,一旦它们全部返回,控制将返回发出信号的代码。因此,在信号之后的closeEvent
函数中的下一行代码将在连接到此信号的所有插槽都返回后执行。
因此,在您的情况下,A对象仍然存在且有效。请注意,关闭窗口小部件不一定会删除它(如注释中的vahancho所述)。
编辑:实际上,这取决于您是否通过cleanup
中的指针操纵A.如果B
没有存储指向A
的指针,那么无论如何都会没问题(因为无论如何都会发出信号,将调用插槽,如果A
不是'在插槽内访问,根本没有问题,无论指定或假设的连接类型。如果cleanup
以某种方式通过指针访问A
,请阅读以下内容:
正如所指出的那样,我确实应该确定只有在你使用Qt::DirectConnection
模式进行此连接时才会出现这种情况。实际上,这种模式产生了我描述的行为,并且被假设(connect
函数的默认参数是Qt::AutoConnection
,它根据上下文自动选择,即从线程到槽的信号' d在另一个线程中运行)
如果您使用Qt::QueuedConnection
或Qt::AutoConnection
假设它,那么您确实可能有未定义的行为,因为对插槽的调用将排队到接收器线程,并且只有在控制返回到这个线程的事件循环。如果在A
实际销毁后发生这种情况,