在 MFC 中调用 EndDialog() 时,类析构函数何时触发?

Posted

技术标签:

【中文标题】在 MFC 中调用 EndDialog() 时,类析构函数何时触发?【英文标题】:In MFC When EndDialog() is called, when does class destructor fire? 【发布时间】:2015-07-11 05:48:52 【问题描述】:

在 MFC 中,对于典型的对话框窗口,当 MFC 调用 OnOK() 时,该函数调用 EndDialog() 函数,并且不知何故调用了类析构函数。

假设我有一个公共变量,一个名为“test”的字符串,在 CDialog 的类中,并且在对话框 OK 按钮的 onBnClick() 事件中,我将这个“test”变量设置为一个值。然后我声明一个对话框的实例,并从我的主窗口的类中调用 DoModal()。我可以从 DoModal() 返回后设置的变量中读取,没问题。

void Dialog1::OnBnClickedOk()

    test = "The test string has been set.";
    OnOK();


void CMainFrame::OnEditTest()

    Dialog1 dlg;
    dlg.DoModal();
    MessageBox(dlg.test, L"Main Frm",0);

这可行,但如果我有一个包含多个字段的对话框,并且每个字段都有一个变量,该怎么办。在调用析构函数之前,如何确定可以从所有变量中读取所有值?我查了 MSDN,我的理解是 OnOK() 函数调用了 EndDialog(),并且在某个时刻,在 EndDialog() 之后,调用了类析构函数。我希望始终能够从 OnBnClick() 事件设置的变量中读取值,但我不知道 MFC 何时调用类析构函数。有谁知道 EndDialog() 触发后何时调用析构函数?

谢谢, 闪电战

【问题讨论】:

在上述代码中,dlg 将一直有效,直到OnEditTest() 返回。因此,您有足够的时间读取任意数量的值。 你是否恰好知道析构函数何时被调用?从堆栈中删除 dlg 时是否调用它?我在 MSDN 中找不到此信息。 Dialog1 是一个常规的 C++ 类,适用 C++ 生命周期规则。 MSDN 没有记录标准 C++。 谢谢。在 C++ 中我还有很多东西要学。 使用 Spy++,您将知道事件的确切顺序。 【参考方案1】:

dlg.DoModal() 返回时,只有它的窗口句柄被销毁。

稍后当dlg 超出范围时调用析构函数。这部分与任何C++ 类相同。

在您的示例中,OnEditTest() 返回时,dlg 超出范围。所以基本上你不用担心,如果你犯了错误,编译器会通知你。

为了测试,您可以添加括号并强制dlg 尽快超出范围:

void CMainFrame::OnEditTest()

    
        Dialog1 dlg;
        dlg.DoModal();
        MessageBox(dlg.test, L"Main Frm",0);
    
    //dlg goes out of scope here and ~dlg() is called

    //Next line will obviously not compile:
    MessageBox(dlg.test, L"Main Frm",0); 

附带说明,如果您将dlg 声明为指针,则必须更加小心。因为您必须手动 delete 指针,并且在 dlg() 被销毁后指针仍然可以访问。但这里不是这样。

【讨论】:

我不知道简单地将代码封装在括号中会导致它超出范围,谢谢。 所以 EndDialog 在 CDialog 窗口关闭时被调用。根据 MSDN:“EndDialog 不会立即关闭对话框。相反,它会设置一个标志,指示对话框在当前消息处理程序返回后立即关闭。”在我的示例中,“当前消息处理程序”是拥有调用 DoModal 的方法的执行线程吗? @Blitz:花括号引入block scopes。这是基本的 C++(和 C)。 感谢您提供有关块作用域的链接。我是 C++ 新手。 我假设 EndDialog 仅在对话框被销毁后返回。如果不是这种情况,文档会说得很清楚。 DoModal 在对话框被销毁后返回。

以上是关于在 MFC 中调用 EndDialog() 时,类析构函数何时触发?的主要内容,如果未能解决你的问题,请参考以下文章

确认 EndDialog 时启动器从未激活

我的 IE 在另一个新对话框的 EndDialog 和 DoModal 上崩溃

当 MFC(功能包)调用 CDockablePane::Serialize() 时?

对话框

在MFC中,一个类如何调用其他类的变量和函数??

MFC 关闭窗口用哪个函数?