Вопрос по exception-handling, qt5, qt, exception, c++ – Как отлавливать исключения в Qt?

16
<code>try
{  // `count()` throws exception
  connect(thread, SIGNAL(started()), engine, SLOT(count()));  
}
catch(const X& e)
{}
</code>

Начиная с Qt-5, я получаю следующую ошибку:

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.

Если я не могу поймать исключения обычным способом, как показано выше, то где мы должны их отлавливать?

Тогда ваше решение в вопросе хорошее Adrian
Может быть, вы должны поместить блок try-catch в функцию count () ... Adrian
#vBx количество бросков smallB

Ваш Ответ

3   ответа
12

: notify, я получил его отсюда (на японском):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;
} 
Что такое MyApplication? Это диалог?
это работает, спасибо
класс MyApplication: общедоступный QApplication
@ B & # X408; & # x43E; & # X432; & # x438; & # x45B; Я не уверен насчет возвращаемого значения. Согласно документации Qt, он будет определять, следует ли распространять события (клавиатура и мышь) на родителя. Но для QApplication, я думаю, у него обычно нет родительского объекта.
Когда он ловит исключение, он возвращает истину. Зачем? Что означает возвращаемое значение? Что если вы вернете false?
15

Именно поэтому Qt не поддерживает выдачу исключений через соединения сигнал / слот. Если вы попробуете это, вы увидите это сообщение:

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.

Как уже упоминалось, можно создать подкласс QApplication и перехватить там ваше исключение, но это будет очень раздражающим способом обработки вещей.

Если возможно, я бы порекомендовал переписать счет так, чтобы он не выкидывал.

What if you can't rewrite 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;
}

What if you want to handle something that could be thrown from anywhere?

Очевидным примером такого рода глобальной озабоченности является неожиданное исключение. Ошибки могут случиться где угодно. Было бы желательно записать как можно больше подробностей о событии, чтобы можно было выявить и устранить причину. В этом случае выwould хочу переопределитьQApplication::notify в вашем собственном подклассе, как показано вответ Джичи, Использование глобального обработчика для глобальных проблем вполне разумно.

SLOT не принимает результат count (). Это макрос SLOT:# define SLOT(a) "1"#a
-1 за то, что не привел ни одного примера, как переопределить это ... все возможные комбинации, которые я пробовал, только приводят к некоторым ошибкам компилятора, и эта информация в этом ответе в основном то, что мы можем видеть из самого журнала отладки qt
да, я считаю, что мне придется переписать это и не бросать. Благодарю. smallB
Поймать его в цикле уведомлений - ужасный способ обработки исключений, потому что это приводит к неинтуитивному потоку управления. Если вам действительно нужно, это довольно просто, и ответ Джичи показывает, как именно.
Абсолютно возможно позвонитьcount(), сохраните результат и передайте результатSLOT еслиSLOTне допускается исключение.
-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;
    }
}
#vBx Вы не используете соединение сигналов / слотов, я что-то упустил? smallB
Это строка, а не вызов функции:SLOT(count()) == "1slot()" (или, может быть, "2slot ()", я не уверен).
@smallB: Сигналы и слоты являются конструкциями, специфичными для QT, а vBx дает вам стандартное решение C ++.
@ Я вижу это, но мой вопрос довольно конкретен. Я думал, что понятие сигнального слота будет хорошей раздачей. Также, если вы заметите, я не спрашиваю, как использовать try catch block. smallB
@smallB: Ваш вопрос никак не связан с Qt. Qt - это C ++; у него могут быть специальные макросы и собственный специальный маленький прекомпилятор и проекты сборки, но этоstill C ++. Тот факт, что вам случается использовать изменения сигналовnothing об обработке исключений.

Похожие вопросы