问题
I am working on developing a Qt application for windows platform. I am facing problem when using exception handling in class hierarchy.
I have Class B object instantiated in a function of Class A. When, due to some reason, an exception is thrown from Class B (and not caught in Class B) it is not being caught in Class A (appropriate try-catch block is present in Class A) and instead the application crashes showing some windows specific error. This type of try-catch mechanism in class hierarchy works perfectly fine in Java.
Example:
This is piece of code of ClassA that is instatiating an object of 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);
}
}
When ClassB dialog is displayed and a button present on the dialog is pressed following piece of code is called:
void ClassB::on_pbThrowExp_clicked()
{
try
{
throw (new QString("Throwing Exception !"));
}
catch(QString *strExceptionMsg)
{
throw strExceptionMsg;
}
catch(...)
{
throw (new QString("Unknown Error"));
}
}
This throws an exception which is caught in ClassB's function but when thrown further it is not caught in ClassA (From where objClassB is instantiated) and the entire application crashes.
I have tried 1 solution where I have re-implemented QApplication’s notify method where, an exception thrown from somewhere in the application, if not caught anywhere, is being caught in re-implemented notify method. But doing this does not stop the application from closing down.
Please confirm if this is even possible in Qt/C++ and if not please point me in direction of an alternative (if available) in Qt.
回答1:
This is an old question, but since there still might be people trying to combine Qt with exception handling, following is a solution that worked for me. It requires c++11 support though.
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;
}
You can use the Application
class as you would the QApplication
, except call the run
function instead of exec
. (Alternatively, rename run
into exec
to hide QApplication
's exec
.)
You can override the message
function to customize error messages. You can also override the proc
function to add some initialization/destruction code before/after exec
.
来源:https://stackoverflow.com/questions/20454542/exception-handling-in-qt-for-class-hierarchy