最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++如何通過(guò)Qt反射機(jī)制實(shí)現(xiàn)數(shù)據(jù)類序列化

 更新時(shí)間:2025年04月23日 08:37:05   作者:永不停轉(zhuǎn)  
在?C++?工程中經(jīng)常需要使用數(shù)據(jù)類,并對(duì)數(shù)據(jù)類進(jìn)行存儲(chǔ)、打印、調(diào)試等操作,所以本文就來(lái)聊聊C++如何通過(guò)Qt反射機(jī)制實(shí)現(xiàn)數(shù)據(jù)類序列化吧

在 C++ 工程中經(jīng)常需要使用數(shù)據(jù)類,并對(duì)數(shù)據(jù)類進(jìn)行存儲(chǔ)、打印、調(diào)試等操作。由于數(shù)據(jù)類中有大量數(shù)據(jù)字段,每次都編寫(xiě)存儲(chǔ)或輸出數(shù)據(jù)內(nèi)容,工作重復(fù)量太大。C++ 不支持用戶自定義的注解,所以沒(méi)辦法使用類似 java 中類似 Lombok 的插件。但是 QT 的屬性系統(tǒng)和 moc 編譯系統(tǒng),為簡(jiǎn)化數(shù)據(jù)類的序列化提供了可能性。

設(shè)計(jì)預(yù)期

  • 保持?jǐn)?shù)據(jù)類的簡(jiǎn)潔,最好通過(guò)類似 Lombok 的注解語(yǔ)法,只讓聲明序列化的數(shù)據(jù)字段支持序列化;
  • 自動(dòng)生成 getter 和 setter 方法;
  • 支持?jǐn)?shù)據(jù)流輸入/輸出;
  • 支持 QDebug 直接輸出對(duì)象內(nèi)容;
  • 能自動(dòng)解包 QPoint、QRect、QVariant 等結(jié)構(gòu)化數(shù)據(jù)。

設(shè)計(jì)思路

使用宏代理注解完成 getter 和 setter 方法的自動(dòng)生成;

使用反射系統(tǒng)結(jié)合宏定義記錄需要序列化的字段信息;

使用基類完成序列化的模板代碼,讓數(shù)據(jù)類繼承序列化基類即可完成數(shù)據(jù)的序列化。

代碼實(shí)現(xiàn)

以下代碼中 Serializable 是數(shù)據(jù)類的基類,在其 cpp 文件中內(nèi)置了許多模板代碼用于支持處理數(shù)據(jù)流及 QDebug 操作。宏 SERIALIZE(className) 用于指定需要序列化的類,宏JSONFIELD(field, alias, ...) 用于指定需要序列化的字段。為了保證數(shù)據(jù)類的輕量化,此處沒(méi)有使用 QObject 類,而是使用了輕量化的 Q_GADGET,這樣在預(yù)編譯時(shí)不會(huì)產(chǎn)生太多的代碼。

// serializable.h
#ifndef SERIALIZABLE_H
#define SERIALIZABLE_H

#include "qjsonobject.h"

#include <QObject>
#include <QMetaObject>
#include <QMetaProperty>
#include <QDebug>
#include <QFile>

#include <QtWidgets/QMessageBox>

// SERIALIZE 宏內(nèi)不能包含 Q_GADGET ,必須在子類中單獨(dú)使用 Q_GADGET,
// 因?yàn)?moc 時(shí)不引入其它頭文件,此處定義Q_GADGET對(duì)子類無(wú)效,子類不會(huì)生成moc文件
//const_cast<className&>(explicit
#define SERIALIZE(className) \
Q_CLASSINFO("base", "Serializable") \
public: \
className(const className &other){ \
    copy(other, *this); \
} \
inline const QMetaObject* getMetaInfo() const override{ \
    return &staticMetaObject; \
}

#ifndef Q_MOC_RUN
// define the tag text as empty, so the compiler doesn't see it
#  define JSON_FLAG
#endif
#define VAR_TYPE(var) decltype(var)

#ifdef CHAIN
#define SETTER(field, alias) \
inline auto set##alias(const __type_##field &value) { \
    field = value; \
return this; \
}
#else
#define SETTER(field, alias) \
inline void set##alias(const __type_##field &value) { \
    field = const_cast<__type_##field>(value); \
}
#endif

#define JSONFIELD(field, alias, ...) \
using __type_##field = decltype(field) ;\
Q_PROPERTY(__type_##field field READ get##alias WRITE set##alias) \
    public: \
    Q_INVOKABLE JSON_FLAG inline QMap<QString, QString> __get##alias##Info__(){ \
        QMap<QString, QString> info; \
        info["name"] = #field; \
        info["alias"] = #alias; \
        info["args"] = QString(#__VA_ARGS__); \
        return info; \
    } \
    inline __type_##field get##alias() const { return field; } \
    inline void set##alias(const __type_##field &value) { \
            field = value; \
    }

class Serializable
{
public:
    Serializable();
    virtual ~Serializable();
    static bool isSubClass(QMetaType type);
    virtual const QMetaObject* getMetaInfo() const = 0;
    void copy(const Serializable &from, Serializable &to);
    void copy(const Serializable &from);
    virtual QString hashCode();
    virtual bool equals(Serializable &obj);
    virtual bool operator==(Serializable &obj);
    virtual QString toString();
    template<typename T>
    T invokeMethod(const QMetaObject *metaInfo, int index);
    virtual QVariant getValue(QString fieldName);
    virtual void setValue(QString fieldName, QVariant value);

    friend QDataStream &operator<<(QDataStream &stream, const Serializable &data);
    friend QDataStream &operator>>(QDataStream &stream, Serializable &data);
    friend QDebug operator<<(QDebug dbg, const Serializable &data);

private:
    QString id;
};

Q_DECLARE_METATYPE(Serializable)

#endif // SERIALIZABLE_H

由于 cpp 文件的代碼太多,此處不再貼出來(lái),需要的請(qǐng)到項(xiàng)目 https://github.com/lsyeei/dashboard 的源碼目錄 /common/ 中查看 serializable.cpp

使用方法

  • 子類繼承 Serializable
  • 子類中須使用宏 Q_GADGET
  • 子類中使用宏 SERIALIZE(className) 開(kāi)啟序列化功能
  • 子類中使用 JSONFIELD(field, alias, ...) 指定哪些字段需要序列化
  • 使用Q_DECLARE_METATYPE(className)注冊(cè)元數(shù)據(jù)類型

說(shuō)明:

  • 使用 SERIALIZE 會(huì)自動(dòng)生成拷貝構(gòu)造函數(shù)
  • 使用 JSONFIELD 指定的字段會(huì)自動(dòng)生成 get和set函數(shù),不必單獨(dú)聲明
    舉例:
class Student : public Serializable
{
 Q_GADGET
 SERIALIZE(Student)
 public:
     Student();
     ~Student();
 private:
     QString name;
     int age;

     JSONFIELD(name, Name)
     JSONFIELD(age, Age)
};
Q_DECLARE_METATYPE(Cunstom)

Student的使用方法:

Student student;
student.setName("li");
student.setAge(15);
qDebug() << student;
QByteArray array;
QDataStream stream(&array, QIODeviceBase::WriteOnly);
stream << student;

項(xiàng)目 Compelling Data Designer 用于數(shù)據(jù)的可視化設(shè)計(jì),軟件采用可擴(kuò)展架構(gòu),支持?jǐn)U展圖形插件、數(shù)據(jù)接口。項(xiàng)目仍在開(kāi)發(fā)中,目前已設(shè)計(jì)完成基本圖形、多屬性配置、動(dòng)畫(huà)等功能。結(jié)合 Serializable 類,項(xiàng)目中還提供了 JSON 序列化的實(shí)現(xiàn)方式。具體介紹見(jiàn): QT 實(shí)現(xiàn) C++ 數(shù)據(jù)類與 json 的轉(zhuǎn)換

以上就是C++如何通過(guò)Qt反射機(jī)制實(shí)現(xiàn)數(shù)據(jù)類序列化的詳細(xì)內(nèi)容,更多關(guān)于C++數(shù)據(jù)類序列化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用C語(yǔ)言打造通訊錄管理系統(tǒng)和教學(xué)安排系統(tǒng)的代碼示例

    使用C語(yǔ)言打造通訊錄管理系統(tǒng)和教學(xué)安排系統(tǒng)的代碼示例

    這篇文章主要介紹了使用C語(yǔ)言打造通訊錄管理系統(tǒng)和教學(xué)安排系統(tǒng)的代碼示例,利用C語(yǔ)言強(qiáng)大的數(shù)組和指針能夠更加清晰地體現(xiàn)設(shè)計(jì)思路:D 需要的朋友可以參考下
    2016-06-06
  • Qt實(shí)現(xiàn)Slider滑塊條組件的示例代碼

    Qt實(shí)現(xiàn)Slider滑塊條組件的示例代碼

    在Qt中我們可以通過(guò)拖拽的方式將不同組件放到指定的位置,本文主要介紹了Qt實(shí)現(xiàn)Slider滑塊條組件的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • C語(yǔ)言深入探索數(shù)據(jù)類型的存儲(chǔ)

    C語(yǔ)言深入探索數(shù)據(jù)類型的存儲(chǔ)

    使用編程語(yǔ)言進(jìn)行編程時(shí),需要用到各種變量來(lái)存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來(lái)分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-07-07
  • 簡(jiǎn)單的socket編程入門(mén)示例

    簡(jiǎn)單的socket編程入門(mén)示例

    這篇文章主要介紹了簡(jiǎn)單的socket編程入門(mén)示例,簡(jiǎn)單實(shí)現(xiàn)client輸入內(nèi)容發(fā)送到server端輸出,需要的朋友可以參考下
    2014-03-03
  • C++/Php/Python/Shell 程序按行讀取文件或者控制臺(tái)的實(shí)現(xiàn)

    C++/Php/Python/Shell 程序按行讀取文件或者控制臺(tái)的實(shí)現(xiàn)

    下面小編就為大家?guī)?lái)一篇C++/Php/Python/Shell 程序按行讀取文件或者控制臺(tái)的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • Opencv實(shí)現(xiàn)綠幕視頻背景替換功能

    Opencv實(shí)現(xiàn)綠幕視頻背景替換功能

    這篇文章主要為大家詳細(xì)介紹了Opencv實(shí)現(xiàn)綠幕視頻背景替換功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C++單例類模板詳解

    C++單例類模板詳解

    這篇文章主要介紹了C++單例類模板,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 用C語(yǔ)言實(shí)現(xiàn)猜數(shù)字

    用C語(yǔ)言實(shí)現(xiàn)猜數(shù)字

    這篇文章主要為大家詳細(xì)介紹了用C語(yǔ)言實(shí)現(xiàn)猜數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • C++?內(nèi)存避坑指南之移動(dòng)語(yǔ)義和智能指針解決"深拷貝"與"內(nèi)存泄漏"的過(guò)程

    C++?內(nèi)存避坑指南之移動(dòng)語(yǔ)義和智能指針解決"深拷貝"與"內(nèi)存泄漏"的過(guò)程

    文章介紹了Java和C++中函數(shù)傳參和對(duì)象生命周期管理的區(qū)別,C++提供了三種傳參方式:值傳遞、引用傳遞和指針傳遞,C++通過(guò)RAII和智能指針(如unique_ptr、shared_ptr和weak_ptr)來(lái)管理堆內(nèi)存,避免內(nèi)存泄漏和雙重釋放,感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • 利用Matlab繪制好看的旋轉(zhuǎn)九邊形

    利用Matlab繪制好看的旋轉(zhuǎn)九邊形

    這篇文章主要為大家介紹了如何利用Matlab繪制超好看的旋轉(zhuǎn)九邊形。文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-03-03

最新評(píng)論

温州市| 万载县| 信丰县| 南皮县| 黑龙江省| 遂川县| 牙克石市| 永胜县| 谷城县| 三都| 吉木乃县| 合川市| 台湾省| 乐清市| 南安市| 大理市| 崇明县| 如东县| 新津县| 丰都县| 贡山| 英吉沙县| 班戈县| 岐山县| 苍梧县| 沐川县| 咸丰县| 铅山县| 阳泉市| 南郑县| 延川县| 新乡县| 明光市| 顺平县| 阿拉尔市| 海盐县| 西丰县| 呼玛县| 察哈| 青阳县| 山丹县|