我正在为Windows平台开发Qt应用程序。在类层次结构中使用异常处理时遇到问题。
我在类A的函数中实例化了B类对象。当由于某种原因,从类B抛出异常(并且未在类B中捕获)时,它不会被捕获到类A中(适当的尝试 - catch块存在于A类中,而应用程序崩溃则显示某些特定于Windows的错误。类层次结构中的这种类型的try-catch机制在Java中完全正常。
示例:
这是ClassA的一段代码,用于实现ClassB的对象(Qt Dialog)
void Class A::on_pbCallB_clicked()
{
try
{
objClassB = new ClassB();
objClassB->show();
}
catch(QString *strExceptionMsg)
{
QMessageBox::critical(this,"Error",*strExceptionMsg);
exit(1);
}
catch(...)
{
QMessageBox::critical(this,"Error","Uknown Error");
exit(1);
}
}
当显示ClassB对话框并按下对话框上的按钮时,会调用以下代码:
void ClassB::on_pbThrowExp_clicked()
{
try
{
throw (new QString("Throwing Exception !"));
}
catch(QString *strExceptionMsg)
{
throw strExceptionMsg;
}
catch(...)
{
throw (new QString("Unknown Error"));
}
}
这会引发一个异常,它会在ClassB的函数中捕获,但是当它被进一步抛出时,它不会被ClassA捕获(从objClassB实例化的地方)并且整个应用程序崩溃。
我尝试了一个解决方案,我已经重新实现了QApplication的通知方法,其中,如果没有捕到任何地方,从应用程序某处抛出的异常将被重新实现的notify方法捕获。但这样做并不能阻止应用程序关闭。
请确认在Qt / C ++中是否可以实现这一点,如果没有,请指出我在Qt中的替代方案(如果有的话)。
答案 0 :(得分:4)
这是一个老问题,但由于可能还有人试图将Qt与异常处理结合起来,以下是一个对我有用的解决方案。它需要c ++ 11支持。
application.hpp:
#ifndef APPLICATION_HPP
#define APPLICATION_HPP
#include <QApplication>
#include <exception>
///
/// This class catches any exceptions thrown inside proc()
/// and shows them using the message() function.
/// The virtual message() function can be overriden to customize
/// how the messages are shown. The default implementation
/// shows them using QMessageBox.
///
class Application: public QApplication
{
public:
Application(int& argc, char* argv[]);
bool notify(QObject* receiver, QEvent* event);
virtual int proc() { return exec(); }
int run();
virtual int message(const std::string&);
private:
std::exception_ptr _M_e = nullptr;
};
#endif // APPLICATION_HPP
application.cpp
#include "application.hpp"
#include <QMessageBox>
Application::Application(int& argc, char* argv[]):
QApplication(argc, argv)
{ }
int Application::run()
{
try
{
int code = proc();
// Check if an exception was thrown and stored in Application::notify
// and if so, rethrow it.
if(_M_e) std::rethrow_exception(_M_e);
return code;
}
catch(std::exception& e)
{
return message(e.what());
}
}
int Application::message(const std::string& message)
{
QMessageBox::critical(0, "Error", QString::fromStdString(message));
return 1;
}
///
/// Qt does not allow exceptions thrown from event handlers
/// to be processed outside the event loop.
/// So we catch them here, store them in _M_e
/// and tell the application to exit.
///
bool Application::notify(QObject* receiver, QEvent* event)
{
try
{
return QApplication::notify(receiver, event);
}
catch(...)
{
_M_e = std::current_exception();
exit();
}
return false;
}
您可以像Application
一样使用QApplication
课程,除了调用run
函数而不是exec
。 (或者,将run
重命名为exec
以隐藏QApplication
的{{1}}。)
您可以覆盖exec
功能以自定义错误消息。您还可以覆盖message
函数,在proc
之前/之后添加一些初始化/销毁代码。