青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

序列化

 

為何需要序列化

我們常常需要將對象持久化或者在通信中傳遞對象,這時我們就會使用到序列化。

C++中的序列化

對于C++這樣的靜態語言來說,序列化往往都很不方便,它對于類型轉換非常敏感和嚴格,所以說想要對C++對象進行序列化那必須對每個序列化的對象進行針對性編碼。

C++中的反序列化

因為C++類型是在編譯時決定的,而序列化是運行時行為,反序列化需要生成的對象類型必須在編譯時決定好,這讓人感到很無力。為了能夠正確的進行反序列化,我們通常會生成一個映射表,將對象的類型所對應的ID一并序列化,這樣就能在運行時通過”預反序列化“得到類型ID,然后查找映射表來得到需要創建的對象類型,然后創建對象進行反序列化。

序列化類型映射表

理想的序列化類型映射表能夠在編譯時生成,因為我們需要序列化的類型都是編譯時決定好了的,所以在編譯時生成其映射表應該理所當然。然而非常尷尬的是,C++如何建立類型ID到類型的映射?它是靜態類型的語言,如果要建立一個類型的映射表,即使使用模板技術也只能做到編譯期映射(也就是需要用編譯時常量進行類型查找,對于運行時的反序列化行為,這顯然是沒有任何作用的)。

一個可行的方案

為了能夠在運行時進行查找,我使用了反序列化輔助對象作為映射類型的載體。這個對象利用模板來關聯序列化類型,它同時也要求序列化類型需要提供默認構造,并且默認構造能夠被其所訪問。

class SerializableObject;

class UnserializerBase{
protected:
UnserializerBase(){}
public:
virtual ~UnserializerBase(){}

public:
virtual SerializableObject* Unserialize(const char*& pData) = 0;
};

template
<typename T>
class Unserializer : public UnserializerBase{
public:
typedef T Object;

public:
Unserializer(){}

public:
SerializableObject
* Unserialize(const char*& pData)
{
Object
* pObj = new Object; // 要求需要序列化支持的類具有默認構造函數
pData += pObj->Unserialize(pData);
return pObj;
}
};

這里顯而易見的是我們的序列化對象必須從SerializableObject派生。

類型ID的計算

簡單起見,我們可以通過C++提供的typeid來計算類型的ID,當然這需要開啟相應編譯開關。序列化類型可以通過模板參數將自身傳遞給某個模板函數來計算其ID,并將這個ID和反序列化輔助類型Unserializer對象建立起映射關系。

template<typename Object>
static ClassIDType BuildClassID()
{
static Unserializer<Object> unserializer;
static std::string name(typeid(Object).name());
static ClassIDType id = std::hash<BinaryData>()(BinaryData(name.c_str(), name.length()));
GetIDMapSerializer()[id]
= &unserializer;
return id;
}



static std::map<ClassIDType, UnserializerBase*>& GetIDMapSerializer()
{
static std::map<ClassIDType, UnserializerBase*> id_unserializer;
return id_unserializer;
}
此處的實現對類型名求了hash值來作為類型ID,至于碰撞的概率和我們的序列化類型數量相比較就可以忽略不計了。并且創建的都是靜態對象,這能夠保證每個序列化類型值生成一次類型ID和反序列化輔助對象。

類型ID的序列化和反序列化

序列化對象對于其ID的序列化和反序列化時的查找過程并不關心,那么我們應該透明的去完成這個過程。同時考慮到序列化對象需要將自身類型進行注冊,我們可以在此時就完成我們的類型ID到反序列化輔助對象的映射的創建。我們在SerializableObject基類和序列化類型之間插入了一個中間模板類,它完成我們剛才提到的映射的創建以及ID的序列化工作(后面講為什么它不完成ID反序列化的工作)。

// 派生類將自身類型傳遞給模板參數
template<typename T>
class Serializable : public SerializableObject{
protected:
static const ClassIDType ID;

public:
typedef T Object;

protected:
Serializable(){ID;}

public:
virtual ~Serializable(){}

public:
template
<typename BufferType>
void Serialize(BufferType& buffer)
{
SaveToBuffer(ID, buffer);
// 這里應該判斷子類序列化是否成功,如果不成功則回滾,暫時未加此功能

static_cast
<Object*>(this)->DoSerialize_(buffer);
}
size_t Unserialize(
const char* pData)
{
return DoUnserialize_(pData);
}
static const ClassIDType GetClassID(){return ID;}

private:
// 通過模板模擬虛函數
template<typename BufferType>
void DoSerialize_(BufferType& buffer){};
virtual size_t DoUnserialize_(const char* pData) = 0;
};

template
<typename T>
const typename Serializable<T>::ClassIDType Serializable<T>::ID = Serializable<T>::BuildClassID<T>();

這里為了能夠減少對存放序列化內容的緩沖區的依賴,我們對序列化接口使用了模板推導,但是這導致我們難以通過虛函數來延遲序列化實現。這里我們采用了一個非標準的實現方式——子類注冊自身類型給父類,并要求子類必須實現一個名為DoSerialize_的模板成員函數,那么我們就可以通過類型轉換去調用子類接口了,達到類似虛函數的功能。

我們最希望的反序列化應該是這樣的:

Type* pObject = dynamic_cast<Type*>(Unserialize(pData));

那么,反序列化接口就不能作為一個模板類的靜態函數。所以我們將這個接口放到了SerializableObject當中

// 此類實現的靜態方法Create用于反序列化
class SerializableObject{
public:
typedef size_t ClassIDType;

protected:
SerializableObject(){}

public:
virtual ~SerializableObject(){}

public:
static SerializableObject* Create(const char*& pData)
{
ClassIDType id
= 0;
pData
+= LoadFromData(id, pData);
std::map
<ClassIDType, UnserializerBase*>& id_serializer = GetIDMapSerializer();
auto iter
= id_serializer.find(id);
if (id_serializer.end() != iter)
{
return (*iter).second->Unserialize(pData);
}
return 0;
}

protected:
template
<typename Object>
static ClassIDType BuildClassID()
{
static Unserializer<Object> unserializer;
static std::string name(typeid(Object).name());
static ClassIDType id = std::hash<BinaryData>()(BinaryData(name.c_str(), name.length()));
GetIDMapSerializer()[id]
= &unserializer;
return id;
}

private:
static std::map<ClassIDType, UnserializerBase*>& GetIDMapSerializer()
{
static std::map<ClassIDType, UnserializerBase*> id_unserializer;
return id_unserializer;
}
};

這樣,基本上我們就可以這樣來定義我們的序列化類型了:

class Test
:
public Serializable<Test>
{
int num_;

public:
explicit Test(int n = 0) : num_(n){}

private:
friend
class Serializable<Test>;
template
<typename BufferType>
void DoSerialize_(BufferType& buffer)
{
SaveToBuffer(num_, buffer);
}

size_t DoUnserialize_(
const char* pData)
{
return LoadFromData(num_, pData);
}
};

這里的SaveToBuffer和LoadFromData是一對序列化幫助函數。

這個序列化和反序列化的實現有個很大的缺點,那就是映射的建立。因為我們使用的是模板,所以說序列化類型不被使用就不會被編譯,那么這個類型就不會被加入到映射中,那么我們的程序就可能出現問題(找不到某個ID所映射的反序列化輔助對象)。解決這個問題的方法就是強制編譯器編譯我們可能會使用到的序列化類型,比如為每個序列化類型定義一個其類型ID的靜態引用,如果是程序中已經使用到序列化類型的話則不必。

示例測試:

假設我們有一套命令系統,各種不同的命令派生自一個命令基類Command,并實現其名為Execute的接口。我們需要將不同的命令類型對象序列化和反序列化(這在網絡通信協議中普遍使用,網絡兩端可定義相同的命令類型,一端只對這個命令對象存儲參數,一端負責實現其執行過程),反序列化過程中不需要關心具體的命令類型,只需要調用其接口Execute便可。

我們的序列化和反序列化非常適合這個系統,下面就給出測試工程代碼,測試工程沒有建立網絡通信,只是體現我們的序列化和反序列化的方式。

下載測試工程源碼


作者: Evil.Ghost 發表于 2011-04-04 19:58 原文鏈接

評論: 0 查看評論 發表評論


最新新聞:
· 蘋果iPad 2通過3C認證 最晚5月國內上市(2011-04-10 09:18)
· 盲目依賴iPhone等工具導航 英國驢友迷路多(2011-04-10 09:14)
· 趣談:想擔任CEO的話,最好是去蘋果工作,其次是微軟,再才是Google(2011-04-10 08:26)
· 騰訊將建立新數據中心,規模為蘋果的兩倍(2011-04-10 08:25)
· 輕量化的微型博客Tumblr(2011-04-10 08:03)

編輯推薦:非戰之罪,從永中Office談起

網站導航:博客園首頁  我的園子  新聞  閃存  小組  博問  知識庫

posted on 2011-04-04 19:58 EvilGhost 閱讀(839) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


導航

統計

常用鏈接

留言簿

隨筆檔案(12)

文章檔案(1)

最新隨筆

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美激情片在线观看| 国产亚洲一级| 亚洲欧美激情在线视频| 亚洲午夜精品久久| 国产精品夜夜嗨| 久久嫩草精品久久久久| 久久午夜羞羞影院免费观看| 亚洲国产精品t66y| 亚洲欧洲美洲综合色网| 麻豆精品在线播放| 一区二区三区四区在线| 一区二区三区高清视频在线观看 | 亚洲一区精彩视频| 亚洲专区在线视频| 精品va天堂亚洲国产| 国产精品久久久久99| 国语精品一区| 亚洲国产美女精品久久久久∴| 欧美精品在线看| 性欧美8khd高清极品| 欧美一级网站| 亚洲精品乱码久久久久| 亚洲午夜激情免费视频| 精品粉嫩aⅴ一区二区三区四区| 亚洲国产精品久久久久婷婷老年 | 欧美日韩在线大尺度| 欧美在线播放视频| 麻豆成人小视频| 亚洲网站啪啪| 久久精品网址| 在线一区二区三区四区五区| 欧美一级欧美一级在线播放| 亚洲精品在线观看免费| 亚洲午夜国产成人av电影男同| 在线观看免费视频综合| 一本色道**综合亚洲精品蜜桃冫| 国产伊人精品| 亚洲精品午夜| 黄色成人片子| 一个色综合av| 在线观看三级视频欧美| 一区二区三区四区五区视频 | 欧美中文日韩| 日韩亚洲欧美一区| 欧美一区二区私人影院日本| 日韩午夜在线电影| 午夜宅男久久久| 亚洲最快最全在线视频| 久久精品成人一区二区三区| 一区二区电影免费在线观看| 久久国产精品99国产精| 亚洲性xxxx| 老色鬼久久亚洲一区二区| 性一交一乱一区二区洋洋av| 欧美国产视频一区二区| 久久免费国产精品1| 欧美日韩综合网| 欧美成人国产| 国产欧美日本一区二区三区| 亚洲国产天堂久久综合网| 国产在线视频不卡二| 一区二区三区欧美| 亚洲激情成人在线| 性欧美18~19sex高清播放| 在线综合欧美| 免播放器亚洲一区| 久久久伊人欧美| 国产精品人人做人人爽| 亚洲日本va在线观看| 在线免费观看欧美| 欧美一区二区三区免费观看视频| 亚洲午夜成aⅴ人片| 欧美成人一区在线| 国产精品日韩一区二区| 亚洲永久免费av| 欧美激情在线有限公司| 欧美成人黑人xx视频免费观看| 国产欧美日韩一区二区三区在线 | 9色精品在线| 亚洲欧洲精品一区| 久久精品夜色噜噜亚洲a∨| 欧美一级午夜免费电影| 欧美日韩一区二区欧美激情| 91久久精品美女| 亚洲国产精品第一区二区| 久久www成人_看片免费不卡| 欧美在线地址| 国产精品乱人伦一区二区| 9久re热视频在线精品| 亚洲美女中出| 欧美1区视频| 男人天堂欧美日韩| 伊人成年综合电影网| 久久成人久久爱| 久久精品盗摄| 国产亚洲va综合人人澡精品| 亚洲伊人色欲综合网| 亚洲欧美日韩精品在线| 欧美色大人视频| 99国产精品视频免费观看一公开| 日韩一级在线| 欧美精品尤物在线| 亚洲精品久久久久久久久久久久久 | 亚洲麻豆国产自偷在线| 日韩一级黄色av| 欧美日韩大陆在线| 亚洲精品视频在线观看免费| 一区二区欧美精品| 欧美精品在线免费| 日韩亚洲欧美成人一区| 一区二区三区欧美| 欧美日韩综合另类| 亚洲一区二区免费在线| 欧美亚洲日本一区| 国产午夜精品在线| 久久本道综合色狠狠五月| 久久免费的精品国产v∧| 在线成人av网站| 美女主播一区| 亚洲人成在线免费观看| 亚洲伦理久久| 欧美日韩综合在线| 午夜精品一区二区三区在线播放| 久久精品国产亚洲一区二区| 黑丝一区二区| 另类尿喷潮videofree| 欧美黄色小视频| 夜夜躁日日躁狠狠久久88av| 欧美色区777第一页| 亚洲午夜国产一区99re久久| 久久国产精品亚洲va麻豆| 精品成人在线视频| 鲁大师成人一区二区三区| 亚洲国产精品99久久久久久久久| 欧美伊人影院| 亚洲午夜羞羞片| 国产亚洲精品激情久久| 久久久亚洲国产美女国产盗摄| 亚洲电影在线播放| 亚洲午夜国产一区99re久久| 国产噜噜噜噜噜久久久久久久久| 久久精品亚洲乱码伦伦中文 | 久久精品日产第一区二区三区| 激情亚洲一区二区三区四区| 美日韩免费视频| 亚洲麻豆av| 久久精品一二三区| 亚洲国产高清在线| 欧美午夜精品久久久久免费视| 欧美一级视频免费在线观看| 欧美黄色aaaa| 亚洲在线免费观看| 黄色亚洲网站| 欧美日本簧片| 性欧美xxxx视频在线观看| 欧美成人中文字幕在线| 亚洲午夜久久久久久久久电影院 | 亚洲天天影视| 激情久久久久久久| 欧美乱人伦中文字幕在线| 亚洲欧美国产三级| 欧美成人dvd在线视频| 亚洲欧美日韩一区二区在线 | 欧美视频日韩| 久久精品国产99国产精品澳门| 亚洲国产精品va在线观看黑人| 欧美一区2区三区4区公司二百| 亚洲国产综合在线| 国产精品麻豆va在线播放| 久久人人爽人人爽爽久久| av成人免费观看| 老色鬼精品视频在线观看播放| 99热这里只有精品8| 国产日韩欧美电影在线观看| 欧美成人中文字幕在线| 亚洲欧美色婷婷| 最新热久久免费视频| 久久精品99| 一区二区三区毛片| 影音先锋另类| 国产精品色网| 欧美精品1区| 久久久久成人精品| 国产精品99久久久久久久女警 | 久久中文在线| 亚洲性视频h| 亚洲娇小video精品| 国产欧美日韩在线 | 国产精品免费小视频| 欧美jjzz| 久久av一区二区三区| 亚洲午夜精品国产| 亚洲区一区二区三区| 久久永久免费| 欧美精品首页| 99av国产精品欲麻豆| 欧美成人69| 久久久精品久久久久| 亚洲愉拍自拍另类高清精品| 亚洲三级国产|