我正在制作具有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";
    }
}


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

10-01 17:19