最近遇到一个朋友,问了我一个刁钻的问题,当你模态弹出一个窗体时,后台把这个窗体的父类给析构了,这个时候会出现什么样的状况?函数
听到问题后我真是一脸懵逼呀!历来没有这么写过代码。oop
随后写了一个简单的测试demo,跟踪了下Qt的源码,得出以下结论:测试
带着这两个问题咱们来研究下Qt的代码ui
测试代码超级简单,就是当咱们的模态窗体弹出时,使用定时器10s后析构了其父类obj对象this
QPushButton * obj = new QPushButton; QTimer::singleShot(10000, this, [&obj]() { delete obj; obj = nullptr; }); QDialog * p = new QDialog(obj); p->exec();
首先咱们来看下模态窗口析构时,是由谁触发的,以下图所示,从堆栈能够很清楚的看到是父类按钮析构时,析构其全部子窗口干的。code
int QDialog::exec() { ... QEventLoop eventLoop; d->eventLoop = &eventLoop; (void) eventLoop.exec(QEventLoop::DialogExec); ... }
当咱们调用QDialog的exec方法时,内部开启了一个QEventLoop事件循环对象
int QDialog::exec() { ... while (!d->exit.loadAcquire()) processEvents(flags | WaitForMoreEvents | EventLoopExec); ... }
这个方法里边就是一直死循环处理咱们的事件,当d->exit.loadAcquire()返回不为false时,事件循环退出,也就是咱们的模态窗体要关闭了。接口
下面咱们来分析d->exit.loadAcquire()这个接口为何返回了真事件
首先我给全部调用d->exit.storeRelease方法的地方都打了断点,发现是在QEventLoop::exit函数中命中断点,看了下调用堆栈,没毛病,一切正常。源码