2013-12-08 153 views
1

我正在開發針對Windows平臺的Qt應用程序。在類層次結構中使用異常處理時,我遇到了問題。Qt中的類層次結構異常處理

我有B類對象在類A的函數中實例化。當由於某種原因從B類拋出異常(並且未在類B中捕獲)時,它不會被捕獲到類A中(適當的嘗試-Aatch塊存在於A類中),而是應用程序崩潰,顯示一些特定於窗口的錯誤。類層次結構中的這種類型的try-catch機制在Java中非常適用。

實施例:

這是一塊的ClassA的代碼被instatiating ClassB的的對象(Qt的對話框)

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的(從哪裏OB異常jClassB被實例化)並且整個應用程序崩潰。

我已嘗試解決方案,我已經重新實現的QApplication的通知方法,其中,從什麼地方拋出的應用程序異常,如果沒有抓到任何地方,正在陷入重新實現notify方法。但是這樣做並不能阻止應用程序關閉。

請確認這是否甚至可以在Qt/C++中使用,如果不是,請在Qt中指向替代方法(如果可用)。

+3

請提供[SSCCE](http://sscce.org/)。很難確切地說明發生了什麼,只是對代碼的描述。 – Mat

+0

http://mattgemmell.com/2008/12/08/what-have-you-tried/? – elyashiv

+0

感謝您的意見。我已經添加了示例代碼和一些信息abt我已經嘗試過。希望這會讓問題更清楚。 –

回答

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。 (另外,重命名runexec隱藏QApplicationexec。)

您可以覆蓋message功能自定義錯誤消息。您也可以覆蓋proc函數以在exec之前/之後添加一些初始化/銷燬代碼。