【问题标题】:Throwing an exception from Q_INVOKABLE method?从 Q_INVOKABLE 方法中抛出异常?
【发布时间】:2017-11-17 01:26:47
【问题描述】:

试图了解基于 Qt/QML 的应用程序的最佳实践,其中我们将方法标记为 Q_INVOKABLE。如果我们从其中一种方法中抛出异常,会有什么后果?

class Class
{
    ...
    Q_INVOKABLE void method() { throw std::logic_error(); }
};

QML 可以处理这个错误吗,或者我会让程序崩溃吗?

【问题讨论】:

    标签: c++ qt exception-handling qml


    【解决方案1】:

    Q_INVOKABLE 宏只是标记函数,以便可以使用QMetaObject::invokeMethod() 调用它。它并没有真正改变 Qt 中处理异常的方式。

    为此,区分通过连接调用的槽和作为普通函数直接调用的槽很重要。如果通过信号槽连接调用方法,则未定义抛出异常时会发生什么,除非您实际处理槽内的异常。即,在您必须写入的插槽中:

    void Class::method() {
        try {
            // code that might throw logic_error
        } catch (std::logic_error &err) {
        }
    }
    

    您不能省略catch() 语句。

    另一方面,如果方法直接作为函数调用,那么直接抛出就可以了。但是,无论在何处调用该方法,都必须对其进行捕获和处理。即,你必须写:

    try {
        obj.method();
    catch (std::logic_error &err) {
        // error-handling
    }
    

    这真的是因为 Qt 应用程序事件循环中的错误处理没有明确定义。请参阅docs on Qt 5.9 了解更多信息。

    【讨论】:

    • 我同意您对其工作原理的回答。话虽如此,我没有看到实现一个函数的意义,该函数完成一些工作,然后在某个时候 throws ,并在函数本身内捕获异常。在这种情况下,使用标准 if then else 处理错误情况似乎更有意义?
    • 那么从字里行间解读——如果我们从 QML 调用一个抛出异常的 C++ 方法,行为是未定义的?
    • @sandwood 一个常见的例子是一个与某些确实抛出异常的外部库接口的插槽。 Qt 本身(几乎)从不抛出标准构建,但许多第三方库大量使用异常。
    • @yano 是的,这似乎是正确的。如果您从 QML 调用它们,则所有异常处理都应在 C++ 类中完成。
    猜你喜欢
    • 2015-03-05
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多