c++ - 带参数默认值的 QMetaMethod::invoke()

标签 c++ qt qt5 qmetaobject qt-slot

在包含默认参数的方法上调用 QMetaMethod::invoke() 时,调用失败。

class MyClass : public QObject
{
    Q_OBJECT
public:
    Q_INVOKABLE MyClass() : QObject(nullptr){}

public slots:
    int MyMethod(int a = 0)
    {
        return a*2;
    }
};


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyClass* object = new MyClass();
    QMetaObject *metaObject = object->metaObject();

    for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
    {
        if(metaObject->method(i).name() == "MyMethod")
        {
            int returnVal;

            //returns false
            metaObject->method(i).invoke(object,
                                         Qt::DirectConnection,
                                         Q_RETURN_ARG(int, returnVal));

            break;
        }
    }

    return a.exec();
}

如果我传递一个 int 作为第一个参数,那么它运行良好。有什么方法可以检索方法参数的默认值,以便我可以传递这些值而不是不传递任何内容?

我本来打算在类中手动存储每个方法的默认值,但这是一个丑陋的黑客行为。

感谢您的宝贵时间。

最佳答案

如果您查看生成的 .moc,您会看到以下内容:

void MyClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    if (_c == QMetaObject::InvokeMetaMethod) {
        MyClass *_t = static_cast<MyClass *>(_o);
        Q_UNUSED(_t)
        switch (_id) {
        case 0: { int _r = _t->MyMethod((*reinterpret_cast< int(*)>(_a[1])));
            if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); }  break;
        case 1: { int _r = _t->MyMethod();
            if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); }  break;
        default: ;
        }
    }
}

如您所见,生成了 2 个方法,可以通过打印具有该名称的方法来验证:

#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>

class MyClass: public QObject
{
    Q_OBJECT
public:
    using QObject::QObject;
public slots:
    int MyMethod(int a = 0){ return a*2;}
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyClass object;
    const QMetaObject *metaObject = object.metaObject();
    for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
    {
        QMetaMethod method = metaObject->method(i);
        if(method.name() == QByteArray("MyMethod"))
            qDebug()<<i<<method.name();
    };
    return 0;
}

#include "main.moc"

输出:

5 "MyMethod"
6 "MyMethod"

那么是什么让他们与众不同呢?参数的数量,所以必须添加一个过滤器,即parameterCount() .

#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>

class MyClass: public QObject
{
    Q_OBJECT
public:
    using QObject::QObject;
public slots:
    int MyMethod(int a = 0){ return a*2;}
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    MyClass object;
    const QMetaObject *metaObject = object.metaObject();
    for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
    {
        QMetaMethod method = metaObject->method(i);
        if(method.name() == QByteArray("MyMethod") && method.parameterCount() == 0)
        {
            int returnVal;
            bool status = method.invoke(&object,
                                        Qt::DirectConnection,
                                        Q_RETURN_ARG(int, returnVal));
            Q_ASSERT(status);
            qDebug()<<returnVal;
        }
    };
    return 0;
}

#include "main.moc"

输出:

0

另一方面,如果您想避免此类问题,您可以使用 QMetaObject::invokeMethod() 进行验证:

MyClass object;
int returnVal;
bool status = QMetaObject::invokeMethod(&object,
                                        "MyMethod",
                                        Qt::DirectConnection,
                                        Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;

关于c++ - 带参数默认值的 QMetaMethod::invoke(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52808662/

相关文章:

c++ - 如何避免 TListView 触发 OnSelectItem 事件(c++ Embarcadero)

c++ - 用Lambda函数重新捕获变量是否合法?

qt - 有没有办法在 Qt Creator 的设计器中组织窗口/屏幕?

c++ - 无法将纹理应用于 Qt OpenGL 中的顶点网格

c++ - 提取 QToolButton Widget 的顶角位置

c++ - 长十六进制值的 vector

qt - 自定义样式 Qt 快速控件

qt - QML 连接 : Implicitly defined onFoo properties in Connections are deprecated

c++ - QPainter 的 setWorldTransform 默认行为?

c++ - QT中如何维护MVC模式