【问题标题】:Qt - passing reference of QJsonObject or QJsonArrayQt - 传递 QJsonObject 或 QJsonArray 的引用
【发布时间】:2014-04-23 05:02:16
【问题描述】:

我正在制作带有 Qt 树视图和 Qt Json 支持的 Json 格式数据编辑器。 我想将 QJsonObject 或 QJsonArray 引用参数传递给函数。

这行得通:

void makeJsonData(QJsonObject &obj) {
  obj.insert("key", 1234);
}

//call makeJsonData()
QJsonObject jobj;
makeJsonData(jobj);
int keysize = jobj.keys().size(); //1, OK.

但不是这样:

//QJsonValue, because it can handle both QJsonObject and QJsonArray
void makeJsonData(QJsonValue &obj) { 
  obj.toObject().insert("key", 1234); //obj is QJsonObject
}

//call makeJsonData()
QJsonObject jobj;
makeJsonData(QJsonValue::fromVariant(jobj)); //fromVariant() to cast QJsonObject to QJsonValue
int keysize = jobj.keys().size(); //0, Fail.

看起来 QJsonValue::toObject() 只是复制参数.. 如何使用一种参数类型同时引用 QJsonObject 和 QJsonArray?

【问题讨论】:

  • QJsonObjectQJsonArray 的方法中使用void* 作为参数类型和dynamic_cast<> 将起作用(如果你转换为指针类型,它会在转换失败时返回null) ...它有点(准备好:非常非常)脏,因为您必须完全处理错误类型的传递,但是您可以同时传递 QJsonValueQJsonArray 而无需进行 .toObject() 调用.
  • @LosFrijoles 感谢您的快速回复!

标签: c++ qt qjson


【解决方案1】:

我认为有几种方法可以解决您的问题:

选项 1(如我的评论中所述)

可以像这样使用动态转换:

bool makeJsonData(void* obj) {
    QJsonObject* asObj = dynamic_cast<QJsonObject*>(obj);
    QJsonArray* asArray = dynamic_cast<QJsonArray*>(obj);

    if (asObj) {
        //do what you would if it were an object
    }
    else if (asArray) {
        //do what you would if it were an array
    }
    else {
        //cast fail. Returning false to tell the caller that they passed bad data
        //an alternate (probably better) would be to throw an exception
        return false;
    }
}

选项 2

老实说,我觉得与void* 开展这项业务是错误的做法。做void* 的东西几乎总是一种代码异味(它消除了编译时检查,使我们免于踩到自己的脚),在这种情况下,我认为你这样做的方式需要工作。此外,dynamic_cast 需要 RTTI,它可能并不总是打开(编译器支持、性能问题等)。

我查看了我机器上的 Qt 头文件,据我所知,QJsonObjectQJsonArray 并没有真正继承任何东西,所以沿着将 void* 更改为基本类型以保持类型检查的外观是行不通的。

我会这样做:

  • 创建两个单独的方法。一种用于处理数组,一种用于处理对象。他们有不同的方法和你可以做的不同的事情,所以这对我来说很有意义。您甚至可以保持相同的名称,以便它们重载。
  • 用另一种方法来处理常用的东西。我假设您的函数正在尝试将一些数据添加到传递的数组或对象中。创建一个创建数据的方法(即QJsonObject createJsonData())并在上述两个方法中调用它。

这个想法是在保持类型检查的同时减少代码重复。使用一种额外的方法来处理这两种情况所花费的时间可能远远少于在意外将某些内容传递给您从未打算传递的 void* 指针后调试代码所花费的时间。

选项 3

或者,您可以使用QJsonValue,将函数的返回类型更改为QJsonValue,并使其返回新对象而不修改原始对象。此外,QJsonValue 类具有那些有趣的isArray/isObject 方法,您可以使用它们来执行前面提到的操作。一个例子:

QJsonValue makeJsonData(const QJsonValue& val) {
    if (val.isObject()) {
        QJsonObject obj = val.toObject();
        //do your stuff, modifying obj as you please (perhaps calling another method so that this can have less repetition
        return QJsonValue(obj);
    }
    else if (val.isArray()) {
        QJsonArray arr = val.toArray();
        //do your stuff, modifying arr as you please (perhaps calling another method so that this can have less repetition
        return QJsonValue(arr);
    }
    else {
        throw "Invalid Value Type";
    }
}

老实说,我更喜欢这种模式,但我知道采用您提到的方式是有原因的,例如避免无偿分配内存。

【讨论】:

  • 哇,非常感谢,这是我见过的最佳答案。我会查看并检查您的选项 3。谢谢。祝你有美好的一天。
【解决方案2】:

您可能需要添加以下内容:

#include <QJsonArray>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 2012-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多