c++ - Qt - 传递 QJsonObject 或 QJsonArray 的引用

标签 c++ qt qjson

我正在制作支持 Qt TreeView 和 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 的引用?

最佳答案

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

选项 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";
    }
}

老实说,我更喜欢这种模式,但我知道有理由采用您提到的方式,例如避免不必要的内存分配。

关于c++ - Qt - 传递 QJsonObject 或 QJsonArray 的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23235122/

相关文章:

c++ - QGraphicsItem只能在堆上创建?

c++ - gcc -I 和 -L 选项似乎不起作用

python - 重复访问多个文件时出错

linux - 生成错误 : QT Headers before X11

c++ - 如何比较两个已解析的文件并将差异附加到第一个?

c++ - QJsonDocument::toJson() 不正确的 double

c++ - QJson用什么来解析JSON的语法?

c++ - 在 Visual C++ 2013 中不能为 "Go To Definition"

c++ - 将成员或非成员函数指针作为参数传递

c++ - 为什么这不会创建悬空引用?