如何在Qt编程中处理初始化失败时的程序终止?

5
MainWindows::MainWindow(QWidget *parent) :
                 QMainWindow(parent) , ui(new Ui::MainWindow) {
      ui->setupUi(this);

      some initialization code here
}

如果初始化失败,我希望能够终止整个应用程序,我该怎么做?

谢谢。

5个回答

14

qApp->exit()this->close()MainWindow的构造函数中调用时,都无法正常工作。

普通的Qt int main()函数看起来像这样:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    MainWindow mainWindow;
    mainWindow.show();

    return application.exec();
}

...而qApp->exit()仅在qApp->exec()/application.exec()主循环内部运行,正如您可以在int main()中看到的那样,您还没有在其中。因此它没有任何效果。

而对于this->close()MainWindow()尚未完成创建并且尚未显示,因此它没有打开 - 如果它没有打开,它就无法关闭。=)

延迟初始化的使用

我认为解决这个问题最简单的方法是将初始化推迟到构造函数完成后:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    MainWindow mainWindow;
    if(mainWindow.Initialize() == false)
        return 0;

    mainWindow.show();
    return application.exec();
}

通常我更喜欢/建议在类的构造函数中初始化,但是为了解决这种不寻常的情况,需要做出一个例外。

使用“失败状态”标志

实现同样效果的其他方法是继续在构造函数中进行初始化,但使用一个标志来标记主窗口已经“初始化失败”:

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    MainWindow mainWindow; //Initialize in constructor, like normal.
    if(mainWindow.Failed()) //Check results.
    {
        return 0;
    }

    mainWindow.show();
    return application.exec();
}

使用异常

异常也是另一种处理这种情况的方法-但要确保捕获它,以便操作系统不显示错误消息(我忘了Windows是否检测)。在初始化时,您自己报告错误,因此可以报告详细信息。

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    try
    {
        MainWindow mainWindow; //Initialize in constructor, like normal.

        mainWindow.show();
        return application.exec();
    }
    catch(...)
    {
        return 0;
    }
}

这看起来是一个很棒(最好的)的答案,但迄今为止没有人欣赏它! - Zingam
@Zingam 这就是我晚了两年参加派对的结果。= P 几个月前我也遇到了同样的问题,所以在找不到更好的解决方案时写了答案。 - Jamin Grey
我只是为了使用异常而使用了try-catch的解决方案!但我敢打赌你的解决方案不会起作用(它对我来说没用过 :)!)你需要使用指针!当MainWindow超出范围时,它将被销毁!你知道我在说什么!基本上:MainWindow * mw; try {mw = new MainWindow} ... bool returnCode = app.exec(); delete mw; return returnCode; - Zingam
我建议不要在构造函数中使用异常,而是有另一个好的选择:在构造函数中使用QTimer::singleShot(0, this, SLOT(init())),并将所有初始化放在这里。init函数将在构造函数返回后调用,在其中您可以使用依赖于事件的函数,如quit和exit。 - Jeka

6
如何使用 exit() 函数?
MainWindows::MainWindow(QWidget *parent) :
                 QMainWindow(parent) , ui(new Ui::MainWindow) {
      ui->setupUi(this);

      //some initialization code here
      if (something_failed)
      {
          exit(1); // terminate process
      }
}

是的,它简单、干净、标准化,并解决了所有问题。 - Alexander Shishenko
1
我担心主窗口的析构函数没有被调用;但也许它只是退出到操作系统,导致内存泄漏。 - CodeLurker
1
这个情况存在一些问题。如果您调用exit(),Qt退出处理程序将不会被调用,因此您可能会遇到托盘图标“幽灵”和其他可能的副作用。 - BiTOk

2
这对我有效:
QMetaObject::invokeMethod(this, "close", Qt::QueuedConnection);

1

你可以使用assert方法来终止程序,它会自动检查条件,如果条件变为false,则终止程序并给出终止的行。语法如下:

Q_ASSERT(condition);


Q_ASSERT在发布模式下无效,在调试模式下用于辅助开发。因此,在这些情况下它实际上不能被使用。 - Robert

0
我想在初始化失败时终止整个应用程序,我该怎么做?
从构造函数中抛出异常。默认情况下,未处理的异常将终止整个应用程序。您还可以调用QCoreApplication :: quit - 但最好仍然抛出异常,在其他地方捕获它,并在事情真正出错时使用QCoreAPplication :: quit。
如果您正在编写文件,仅调用exit可能会导致数据丢失。

@Fenix 不完全正确:当在主窗口的构造函数中调用quit()时,通常不会产生任何效果,因为此时事件循环(QCoreApplication::exec())尚未运行。 - alexisdm
@alexisdm:你应该重新阅读我的帖子:“抛出异常,在其他地方捕获它,并使用QCoreApplication :: quit”。 - SigTerm
主窗口通常在调用 qApp->exec() 之前创建,因此即使您捕获了异常,调用 qApp->quit() 仍然没有任何效果,您可以选择不调用 qApp->exec() - alexisdm
@Alexisdm:那就不要捕获它,让其终止就好了,呵呵。这并非什么高深的学问。虽然这个方法比调用exit()(不在QApplication中的那个)更好。 - SigTerm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接