How to catch exceptions in Qt?

前端 未结 3 1162
青春惊慌失措
青春惊慌失措 2021-02-01 18:05
try
{  // `count()` throws exception
  connect(thread, SIGNAL(started()), engine, SLOT(count()));  
}
catch(const X& e)
{}

As of Qt-5, I get follow

相关标签:
3条回答
  • 2021-02-01 18:13

    If someone needs an example code to override QApplication::notify, I got one from here (in Japanese): 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 讨论(0)
  • 2021-02-01 18:18

    You can try this for an example, to see that your solution is good:

    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 讨论(0)
  • 2021-02-01 18:28

    where am I supposed to catch it?

    This is exactly why Qt does not support throwing exceptions across signal/slot connections. If you try it, you'll see this message:

    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.

    As it mentions, it is possible to subclass QApplication and catch your exception there, but that will be a very annoying way of handling things.

    If possible, I would recommend rewriting count such that it does not throw.


    What if you can't rewrite count()?

    For example, what if count() is part of a function in a 3rd-party library that you're using?

    No slot in any official Qt library throws, so if you're using a third-party library with a slot that throws, it's probably a sign that it's not a good library. If you want to use it anyway, I recommend that rather than catching it in QApplication::notify, that you instead create an adapter.

    What does that mean? First create an object that takes in your sketchy third-party object in the constructor. In it, write a slot that wraps a call to the throwing slot with a try/catch block. Now instead of connecting to the sketchy third-party object's slot, connect to your newly create object's slot.

    Doing the exception catching this way keeps related code together, and prevents QApplication::notify from filling up with a bunch of unrelated try/catch blocks if you encounter more than one of these problematic functions.

    For example:

    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?

    The obvious example of this sort of global concern is an unexpected exception. Mistakes can happen anywhere. It would be desirable to log as many details about the event as possible so the cause could be identified and corrected. In this case, you would want to reimplement QApplication::notify in your own subclass as shown in jichi's answer. Using a global handler for global concerns is quite reasonable.

    0 讨论(0)
提交回复
热议问题