首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

自製 C++ 序列化庫:基於成員變數註冊的 XML 互轉實現

     編輯:關於C++

前言

Boost.Serialization 透過運算符重載實現串流讀寫,而本庫採用「成員變數註冊」機制:在建構函數中註冊可序列化欄位,自動生成讀寫邏輯,並支援與 XML 雙向轉換。雖效能非極致、有侵入式代碼,但適合特定領域需求 (配置持久化、狀態儲存、網路協議)。

一、使用範例

1. 定義可序列化類別


class TestTree : public VL_SerializableObject {
public:
    VInt IntegerMember;
    VUnicodeString StringMember;
    VL_AutoPtr LeftTree;
    VL_AutoPtr RightTree;

    TestTree() {
        VL_REGISTER_SERIALIZABLE_FIELD(TestTree, IntegerMember);
        VL_REGISTER_SERIALIZABLE_FIELD(TestTree, StringMember);
        VL_REGISTER_SERIALIZABLE_FIELD(TestTree, LeftTree);
        VL_REGISTER_SERIALIZABLE_FIELD(TestTree, RightTree);
    }
};

2. 註冊類別並序列化


VL_Serializer Serializer;
VL_REGISTER_SERIALIZABLE_CLASS(&Serializer, TestTree);

// 建構物件樹
VL_AutoPtr Root = new TestTree;
Root->IntegerMember = 10;
Root->StringMember = L"Root";

VL_AutoPtr Left = new TestTree;
Left->IntegerMember = 20; Left->StringMember = L"Left";
Root->LeftTree = Left;

VL_AutoPtr Right = new TestTree;
Right->IntegerMember = 30; Right->StringMember = L"Right";
Root->RightTree = Right;

// 序列化 → XML
VL_CommonObject SerializedObject = Serializer.Serialize(Root.Object());
VL_XMLDocument Document;
Document.GetRootElement()->SetName(L"SerializedObject");
SerializedObject.SaveToXML(Document.GetRootElement());
VL_FileStream Stream(FileName, VL_FileStream::vfomWrite);
Document.Save(&Stream, true);

3. 輸出 XML 範例




  
    
      
    
    
      
        
        
        
        
      
    
    
      
        
        
        
        
      
    
    
  

二、核心架構設計

1. 欄位序列化器多態體系


class FieldSerializerBase {
public:
    virtual void Serialize(VL_Serializer* serializer, VL_CommonObject& classObject) = 0;
protected:
    VUnicodeString FFieldName;
};

// 基本型別特化
template
class FieldSerializer<_Type, FIELD> : public FieldSerializerBase { ... };

// 指標型別
template
class FieldSerializer<_Type, _Field*> : public FieldSerializerBase { ... };

// 智慧指標 VL_AutoPtr
template
class FieldSerializer<_Type, VL_AutoPtr<_Field>> : public FieldSerializerBase { ... };

2. 類別註冊與選擇


class VL_Serializer {
    class ClassSerializerBase {
        virtual bool Accept(VL_SerializableObject* obj) = 0;
        virtual VUnicodeString GetClassTypeName() = 0;
    };
    template
    class ClassSerializer : public ClassSerializerBase {
        bool Accept(VL_SerializableObject* obj) override {
            return dynamic_cast<_Type*>(obj) != nullptr;
        }
    };
    List FClassSerializers;
    
    void RegisterClass(ClassSerializerBase* cs) { FClassSerializers.Add(cs); }
    ClassSerializerBase* SelectClass(VL_SerializableObject* obj) { ... }
    VL_CommonObject Serialize(VL_SerializableObject* obj) { ... }
};

3. 巨集簡化註冊


#define VL_REGISTER_SERIALIZABLE_CLASS(SERIALIZER, CLASS) \
    do { (SERIALIZER)->RegisterClass(new VL_Serializer::ClassSerializer(L#CLASS)); } while(0)

#define VL_REGISTER_SERIALIZABLE_FIELD(CLASS, FIELD) \
    do { AddFieldSerializer(this, &CLASS::FIELD, L#FIELD); } while(0)

三、關鍵實現細節

  • VL_CommonObject:統一型別載體,支援基本型別、類別、Null、Error
  • VL_AutoPtr:智慧指標,序列化時遞迴處理
  • VL_SerializableObject::Serialize:遍歷所有欄位序列化器呼叫 Serialize
  • VL_Serializer::Serialize:選擇類別序列化器 → 建立 ClassObject → 呼叫物件 Serialize → 返回 CommonObject
  • XML 輸出:VL_CommonObject::SaveToXML 遞迴生成 DOM

四、優缺點與適用場景

優點缺點
聲明式欄位註冊,無樣板代碼侵入式:需繼承基類、建構函數註冊
原生支援 XML 互轉效能非極致 (中間物件、動態分配)
支援巢狀物件、智慧指標遞迴不支援版本演進、Schema 驗證
型別安全 (編譯期檢查欄位指標)依賴自定義型別系統 (VInt, VUnicodeString...)

適用:工具類專案、配置系統、遊戲存檔、特定協議編解碼。

五、現代化改進方向

  • C++17 std::variant/std::any 替代 VL_CommonObject
  • 反射 (C++26 提案) / 魔術巨集 自動掃描欄位,免手動註冊
  • nlohmann::json / cereal / Boost.Serialization 等成熟庫替代
  • 零拷貝序列化 (Cap'n Proto, FlatBuffers) 適用高效能場景
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved