Qt/Qml和方法重载

gpl*_*lus 10 c++ qt moc qml

刚刚从Qml中调用重载的C++方法并尝试理解其背后的原因时,遇到了Qt框架的奇怪行为.假设我有一个QList<QVariant>类似于以下方法的类:

...
Q_SLOT void append(const QVariant &item);
Q_SLOT void append(const QVariantList &items);
Q_SLOT void insert(int index, const QVariant &item);
Q_SLOT void insert(int index, const QVariantList &items);
...
Run Code Online (Sandbox Code Playgroud)

QML:

onclicked: {
  var itemCount = myListObject.size();
  myListObject.insert(itemCount, "Item " + (itemCount + 1));
}
Run Code Online (Sandbox Code Playgroud)

Qt的某种方式决定将调用void insert(int index, const QVariantList &items)与过载items参数设置为一个null QVariant空的QVariantList,而不是void insert(int index, const QVariant &item)具有过载QStringQVariant.

现在,如果我按如下方式更改声明的顺序,它将按预期工作:

Q_SLOT void insert(int index, const QVariantList &items);
Q_SLOT void insert(int index, const QVariant &item);
Run Code Online (Sandbox Code Playgroud)

我在Qt框架的文档中找不到任何关于声明顺序以及它如何影响调用期间方法解析方式的内容.

有人可以解释一下吗?谢谢.

tro*_*ane 4

这个问题与 JavaScript 中的重载有关。一旦你了解了它——你就会明白代码“奇怪行为”的原因。只需看一下Javascript 中的函数重载 - 最佳实践即可。

简而言之 - 我建议您下一步:因为您可以QVariant在两侧(QML 和 Qt/C++)操作变量 - 将变量作为参数传递,并根据需要在 Qt/C++ 端处理它。

你可以使用这样的东西:

您的 C++ 类已创建并传递给 QML(例如作为setContextProperty("TestObject", &tc)):

public slots:
    Q_SLOT void insert(const int index, const QVariant &something) {
        qDebug() << __FUNCTION__;
        if (something.canConvert<QString>()) {
            insertOne(index, something.toString());
        } else if (something.canConvert<QStringList>()) {
            insertMany(index, something.toStringList());
        }
    }

private slots:
    void insertOne(int index, const QString &item) {
        qDebug() << __FUNCTION__ << index << item;
    }

    void insertMany(int index, const QStringList &items) {
        qDebug() << __FUNCTION__ << index << items;
    }
Run Code Online (Sandbox Code Playgroud)

在你的QML中的某个地方:

Button {
    anchors.centerIn: parent
    text: "click me"
    onClicked: {
        // Next line will call insertOne
        TestObject.insert(1, "Only one string")
        // Next line will call insertMany
        TestObject.insert(2, ["Lots", "of", "strings"])
        // Next line will call insertOne
        TestObject.insert(3, "Item " + (3 + 1))
        // Next line will call insertOne with empty string
        TestObject.insert(4, "")
        // Next line will will warn about error on QML side:
        // Error: Insufficient arguments
        TestObject.insert(5)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你能提到 javascript 重载系统中具体是什么引起了这种行为吗? (4认同)