2012-04-09 3 views
12
Qt는-5로

Qt에서 예외를 잡는 방법?

try 
{ // `count()` throws exception 
    connect(thread, SIGNAL(started()), engine, SLOT(count())); 
} 
catch(const X& e) 
{} 
, 나는 오류 다음 얻을 : 위의 그림과 같이 I는 기존의 방법으로 예외를 잡을 수없는 경우

Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must not let any exception whatsoever propagate through Qt code. If that is not possible, in Qt 5 you must at least re-implement QCoreApplication::notify() and catch all exceptions there.

는, 그럼 우리는 사람을 잡기로되어있다?

+0

어쩌면 당신은 수() 함수에 try-catch 블록을 넣어해야합니다. .. – Kobe

+0

#vBx 카운트가 – smallB

+1

을 던졌습니다 그렇다면 질문에 제공된 솔루션이 좋음 – Kobe

답변

8

where am I supposed to catch it?

이 Qt는 신호/슬롯 연결을 통해 던지는 예외를 지원하지 않는 이유를 정확하게이다. 이 언급대로의 QApplication를 서브 클래스하고 거기 예외를 잡을 수 있으며,

Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must reimplement QApplication::notify() and catch all exceptions there.

,하지만 그 일을 처리하는 매우 성가신 방법이 될 것입니다 : 당신이 그것을하려고하면이 메시지가 표시됩니다.

가능하면 카운트를 다시 쓰지 않는 것이 좋습니다.


count()를 다시 쓸 수 없다면?

예를 들어, count()가 사용중인 타사 라이브러리의 함수의 일부인 경우 어떻게해야합니까?

공식 Qt 라이브러리에는 슬롯이 없습니다. 따라서 슬롯이있는 타사 라이브러리를 사용하는 경우에는 좋은 라이브러리가 아니라는 신호 일 수 있습니다. 어쨌든 사용하고 싶다면 QApplication::notify에 잡기보다는 어댑터를 생성하는 것이 좋습니다.

그 의미는 무엇입니까? 먼저 생성자에서 스케치 된 타사 객체를 가져 오는 객체를 만듭니다. 그 안에 try/catch 블록을 사용하여 던지는 슬롯에 호출을 래핑하는 슬롯을 작성하십시오. 이제 스케치 된 타사 객체의 슬롯에 연결하는 대신 새로 생성 된 객체의 슬롯에 연결하십시오.

이런 식으로 예외를 잡으면 관련 코드가 유지되고 문제가 많은 함수가 두 개 이상 발견 될 경우 QApplication::notify이 관련없는 try/catch 블록으로 채워지는 것을 방지합니다. 예를 들어

:

class BadCounter { 
Q_OBJECT 
public slots: 
    void count() { throw CounterError("unable to count"); } 
}; 

class CounterAdaptor { 
Q_OBJECT 
    BadCounter* counter_; 
public: 
    CounterAdaptor(BadCounter* counter) { 
    counter_ = counter; 
    } 
public slots: 
    void count() { 
    try { 
     counter_->count(); 
    } catch (const CounterError& e) { 
     std::cerr << e.what() << std::endl; 
    } 
    } 
}; 

int main() { 
    BadCounter engine; 
    CounterAdaptor adaptor(&engine); 
    QThread* thread = new QThread(); 
    connect(thread,SIGNAL(started()),&adaptor,SLOT(count())); 
    thread.start(); 
    ... // etc... 
    delete thread; 
} 

당신이 어디에서 발생 될 수있는 일을 처리하려면?

이러한 글로벌 관심사의 명백한 예는 예상치 못한 예외입니다. 실수는 어디서나 발생할 수 있습니다. 원인을 확인하고 수정할 수 있도록 이벤트에 대한 세부 정보를 가능한 한 많이 기록하는 것이 바람직합니다. 이 경우 jichi's answer과 같이 사용자 고유의 서브 클래스에서 QApplication::notify을 다시 구현해야합니다. 글로벌 관심사에 대해 글로벌 처리기를 사용하는 것은 상당히 합리적입니다.

+0

예, 저는 이것을 다시 고쳐야하고 던지지 않을 것입니다. 감사. – smallB

+0

'count()'를 호출하고 결과를 저장 한 다음 SLOT이 예외를 throw 할 수없는 경우 결과를 SLOT에 전달할 수 있습니다. –

+0

SLOT은 count()의 결과를 가져 오지 않습니다. 이것은 SLOT 매크로입니다 : # define SLOT (a) "1"# a' – cgmb

-8

당신은 당신의 솔루션이 좋은 것을보고, 예를 들어이 시도 할 수 있습니다 :

int f() 
{ 
    throw 1; 
    return 5; 
} 

void g(int x) 
{ 
    cout << x << endl; 
} 

int main() 
{ 
    try { 
      g(f()); 
    }catch(int) 
    { 
     cout << "Caught exception" << endl; 
    } 
} 
+0

#vBx 신호/슬롯 연결을 사용하지 않습니다. 무엇인가 놓친 것입니까? – smallB

+0

@smallB : 신호와 슬롯은 QT 관련 구문입니다. vBx가 제공하는 것은 표준 C++ 솔루션입니다. –

+0

@Als 나는 그것을 볼 수 있지만 내 질문은 QT 특정 있습니다. 나는 신호 슬롯의 개념이 좋은 것을 줄 것이라고 생각했다. 또한 try catch 블록을 사용하는 방법을 묻지 않습니다. – smallB

6

사람의 QApplication를 오버라이드 (override) 할 수있는 예제 코드를 필요로하는 경우 : 내가 (일본어로) 여기에서 하나있어, 통지 : http://www.02.246.ne.jp/~torutk/cxx/qt/QtMemo.html

#include "MyApplication.h" 
#include <exception> 

MyApplication::MyApplication(int& argc, char** argv) : 
    QApplication(argc, argv) {} 

bool MyApplication::notify(QObject* receiver, QEvent* event) { 
    bool done = true; 
    try { 
    done = QApplication::notify(receiver, event); 
    } catch (const std::exception& ex) { 
    // ログや何らかの回復処理 
    } catch (...) { 
    // ログや何らかの回復処理 
    } 
    return done; 
} 
+0

MyApplication이란 무엇입니까? 그게 대화 야? – Petr

+1

class MyApplication : public QApplication – jichi

+0

감사합니다. – Petr

관련 문제