昨天晚上寫了部分序列化,結果睡着了....今天繼續完善.. 明天的四級反正是裸考了,無所謂了 。。。。
昨天寫的那個隻能實作單一類型的簡單序列化 ,但是原理卻是一樣..
今天這個可以實作不同的類的序列化,但是注意的一點是我們發現前天的序列化類實作了模闆 ..可以正常的序列化反序列化
如果我們将其抽象出來從一個基類派生,那麼模闆就顯得不好處理了,這裡最笨的方法使用到多重繼承 實作多個基類.然後再将這些基類進行進一步的抽象成一個更高的基類.讓我們的類從這個繼承樹最頂層繼承,我不知道微軟在MFC 和Sun在 java的對象流中是如何處理這些泛型類的 ...但是
如果像我上面這樣處理泛型 ,可能需要寫很多份代碼...雖然說實際開發中對于模闆的使用 泛型化參數不會很多 ,但是這樣的問題總是需要一個更好的解決方案來處理各種情況 。 我是想不出來,求神解答。。。。
由于對于泛型化類的處理不是一時半刻能弄出來 ,下面我接着昨晚上的做 ,我這裡隻處理C++中的非泛化的類 ,或許哪天我就明白了 。。。
昨天 JXXXXXXXX提出說隻能實作一個類.于是我修改了下 ,隻要繼承自Base的類都可以實作序列化 ......具體代碼如下
還有的一點從檔案---->記憶體--------->對象的恢複 沒有構造函數的調用 ,這一點很神奇 。。。
我們成功的恢複了2個對象但是卻沒有發生構造函數的調用...之是以我這種序列化方式能成功 ,肯定是在編譯器内部對于這種方式做了某種
支撐是以我說微軟MFC的序列化方式可能是這種方式。。。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5ybu9CXmd3cvw1b09Gaw9CX05WZpx2YvwVZu9mex9CXt92YuEXcuUGajF2Yn1Wavw1LcpDc0RHaiojIsJye.gif)
#include <iostream>
#include <fstream>
#include <string>
using namespace std ;
class Base
{
public:
/* Base類型提供了統一的實作 ,所有需要序列化的類必須繼承自Base類 包括成員對象
* LoadObject LoadObject 在這裡不需要多态機制 單獨作為功能的實作
* length 為對象的實際長度 為了避免在記憶體重配置設定過多的記憶體浪費空間
* long length=sizeof(*obj) ; //不可以這樣做因為 我們發現實際上sizeof這個運算符
* 在操作的時候擷取的是目前運作時類型所指對象的大小 如果向上轉型那麼會進行窄化處理 獲得的大小是1 是以這裡要傳遞實際大小
* LoadObject LoadObject作為Base的靜态方法分别提供序列化和反序列化的功能
*/
static void StoreObject(Base *obj,string file,int length)
{
cout<<"對象寫入到檔案..."<<endl ;
ofstream *o=new ofstream(file.c_str()) ;
o->write((char*)obj,length) ;
o->close() ;
delete o ;
}
static Base* LoadObject(string file,int length)
{
cout<<"從檔案恢複對象..."<<endl ;
if(Base::tem_object!=NULL)
return Base::tem_object ;
char *buf=new char[length] ;
ifstream i(file.c_str()) ;
i>>buf ;
Base *p=(Base*)buf ;
Base::tem_object=p ;
i.close() ;
return (p);
}
/*
* 構造器用做一些初始化操作
*/
Base()
{
cout<<"基類構造中..."<<endl; }
* 釋放反序列化時候配置設定的空間
virtual ~Base()
if(NULL==Base::tem_object)
delete Base::tem_object ;
Base::tem_object=NULL ;
}
private:
* 暫存加載的對象,對于同一個對象無論LoadObject多少次 加載的永遠隻是
* 傳回的同一份記憶體即同一個對象,直到這個對象的聲明周期完畢,那麼再次加載會是不同的對象
static Base *tem_object;
};
Base * Base::tem_object=NULL ; //必須初始化靜态指針
//序列化類Data
class Data :public Base
{
private :
int data ;
Data(int x)
{
cout<<"Data構造中..."<<endl ;
this->data=x;
void OutPut()
cout<<"Data.data="<<this->data<<endl ;
} ;
//序列化類MyObject
class MyObject :public Base
{
public :
MyObject(int x)
{
cout<<"MyObject 構造中.."<<endl;
this->x=x ;
~MyObject()
{
MyObject ShowX() //一段最簡單的代碼
cout<<"x="<<x<<endl ;
return (*this) ;
int x ;
} ;
int main()
{
string file1="c:\\data.txt" ;
string file2="c:\\myobject.txt" ;
int len1=sizeof(Data) ;
int len2=sizeof(MyObject) ;
* 序列化測試
//測試對象1 ...
Data *d=new Data(8);
Base::StoreObject(d,file1,len1) ;
//測試對象2
MyObject *obj=new MyObject(33) ;
Base::StoreObject(obj,file2,len2) ;
/*
* 反序列化測試。。
((Data*)Base::LoadObject(file1,len1))->OutPut() ;
((MyObject*)Base::LoadObject(file2,len2))->ShowX() ;
delete d ;
delete obj ;
return 0 ;
}
操蛋的是睡覺之前出BUG了 ,明天要帶着BUG裸考了 。。
BUG1 同時序列化 2個以上的對象 如果序列化和反序列化放在一起了 就像下面的代碼
Data *d=new Data(43);
MyObject *obj=new MyObject(13) ;
Base::StoreObject(obj,file2,len2) ;
((MyObject*)Base::LoadObject(file2,len2))->ShowX() ;
發現Data類的域中的x的值居然和MyObject類的成員資料是一樣的 。。。 但是如果像下面這樣一次處理一個 就不會有問題 。
Data *d=new Data(43);
BUG2 如果先調用如下
然後把上述代碼注釋掉,在調用如下,在從檔案加載 就會出現值的亂碼
相反的 如果一次性把序列化和反序列化寫在一起 ,那麼即使下次調用多次也不會出問題,,,
算了考完試再繼續Debug吧...哪位願意幫忙調試下。。。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5ybu9CXmd3cvw1b09Gaw9CX05WZpx2YvwVZu9mex9CXt92YuEXcuUGajF2Yn1Wavw1LcpDc0RHaiojIsJye.gif)