我想用CArchive类来读写我自己写的一个类的对像
我查了一下我自己写的类要是一个能串行化的类MSDN上写的好像有二种方法
#undef AFX_API
#define AFX_API AFX_EXT_CLASS
《你的类的定义\\myclass》
#undef AFX_API
#define AFX_API然后重写myclass::Serialize
我不知道这个函数要怎么写另一种
定义该类时,在类说明中使用DECLARE_SERIAL(CLASSNMAE)宏;
定义一个不带参数的构造函数(默认构造函数);
在类的实现文件中使用IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)宏;
覆盖Serialize成员函数。(如果直接调用Serialize函数进行序列化读写,可以省略前面三步。)
IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)在VC2005中有三个参数不知道怎么设置第三个参数 IMPLEMENT_SERIAL(class_name, base_class_name, wSchema);
myclass::Serialize也要重写
有没有人教我怎么写myclass::Serialize,和
MPLEMENT_SERIAL(class_name, base_class_name, wSchema)第三个参数怎么设置还有个问题就是CArchive ar;
直接用ar.writeobjec(类对像)把对像写进去吗?
我查了一下我自己写的类要是一个能串行化的类MSDN上写的好像有二种方法
#undef AFX_API
#define AFX_API AFX_EXT_CLASS
《你的类的定义\\myclass》
#undef AFX_API
#define AFX_API然后重写myclass::Serialize
我不知道这个函数要怎么写另一种
定义该类时,在类说明中使用DECLARE_SERIAL(CLASSNMAE)宏;
定义一个不带参数的构造函数(默认构造函数);
在类的实现文件中使用IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)宏;
覆盖Serialize成员函数。(如果直接调用Serialize函数进行序列化读写,可以省略前面三步。)
IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)在VC2005中有三个参数不知道怎么设置第三个参数 IMPLEMENT_SERIAL(class_name, base_class_name, wSchema);
myclass::Serialize也要重写
有没有人教我怎么写myclass::Serialize,和
MPLEMENT_SERIAL(class_name, base_class_name, wSchema)第三个参数怎么设置还有个问题就是CArchive ar;
直接用ar.writeobjec(类对像)把对像写进去吗?
if (ar.IsStoring())
{
ar << m_int;
}
else
{
ar >> m_int;
}
另外也不是你说的两种方法,其实就是一种方法:序列化:创建可序列化的类使类可序列化需要五个主要步骤。下面列出了这些步骤并在以后章节内进行了解释: 1. 从 CObject 派生类(或从 CObject 派生的某个类中派生)。
2. 重写 Serialize 成员函数。
3. 使用 DECLARE_SERIAL 宏(在类声明中)。
4. 定义不带参数的构造函数。
5. 为类在实现文件中使用 IMPLEMENT_SERIAL 宏。
如果直接调用 Serialize 而不是通过 CArchive 的“>>”和“<<”运算符调用,则序列化不需要最后三个步骤。从 CObject 派生类
在 CObject 类中定义了基本的序列化协议和功能。正如在 CPerson 类的下列声明中所示,通过从 CObject 中(或从 CObject 的派生类中)派生类,可获得对 CObject 的序列化协议及功能的访问权限。重写 Serialize 成员函数
在 CObject 类中定义的 Serialize 成员函数实际上负责对捕获对象的当前状态所必需的数据进行序列化。Serialize 函数具有 CArchive 参数,该函数使用其来读写对象数据。CArchive 对象具有成员函数 IsStoring,该成员函数指示 Serialize 正在存储(即正在写入数据)还是正在加载(即正在读取数据)。用 IsStoring 的结果作为参考,使用输出运算符 (<<) 将对象数据插入到 CArchive 对象中或使用输入运算符 (>>) 提取数据。假定一个类是从 CObject 派生的并具有两个新成员变量,分别为 CString 和 WORD 类型。下列类声明段显示了新成员变量和重写的 Serialize 成员函数的声明:class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
// empty constructor is necessary
CPerson(){}; CString m_name;
WORD m_number; void Serialize( CArchive& archive );
// rest of class declaration
};重写 Serialize 成员函数 1. 调用 Serialize 的基类版本以确保序列化对象的继承部分。
2. 插入或提取您的类所特定的成员变量。
输出运算符及输入运算符与存档类交互作用以读写数据。下面的示例显示了如何实现以上声明的 CPerson 类的 Serialize: void CPerson::Serialize( CArchive& archive )
{
// call base class function first
// base class is CObject in this case
CObject::Serialize( archive ); // now do the stuff for our specific class
if( archive.IsStoring() )
archive << m_name << m_number;
else
archive >> m_name >> m_number;
}也可使用 CArchive::Read 及 CArchive::Write 成员函数来读写大量未键入的数据。使用 DECLARE_SERIAL 宏
在支持序列化的类的声明中需要 DECLARE_SERIAL 宏,如下所示:class CPerson : public CObject
{
DECLARE_SERIAL( CPerson )
// rest of declaration follows...
};
定义不带参数的构造函数
反序列化对象(从磁盘上加载)后,MFC 重新创建这些对象时,需要一个默认的构造函数。反序列化进程将用重新创建对象所需的值填充所有成员变量。可将该构造函数声明为公共的、受保护的或私有的。如果使该构造函数成为受保护的或私有的,请确保它将仅由序列化函数使用。该构造函数必须使对象处于这样一种状态:必要时,可允许将其安全删除。注意 如果忘记在使用 DECLARE_SERIAL 及 IMPLEMENT_SERIAL 宏的类中定义不带参数的构造函数,将在使用 IMPLEMENT_SERIAL 宏的行上得到“没有可用的默认构造函数”编译器警告。
在实现文件中使用 IMPLEMENT_SERIAL 宏
IMPLEMENT_SERIAL 宏用于定义从 CObject 中派生可序列化类时所需的各种函数。在类的实现文件 (.CPP) 中使用这个宏。该宏的前两个参数是类名和直接基类的名称。该宏的第三个参数是架构编号。架构编号实质上是类对象的版本号。架构编号使用大于或等于零的整数。(请不要将该架构编号与数据库术语混淆。)MFC 序列化代码在将对象读取到内存时检查该架构编号。如果磁盘上对象的架构编号与内存中类的架构编号不匹配,库将引发 CArchiveException,防止程序读取对象的不正确版本。如果要使 Serialize 成员函数能够读取多个版本(即,读取用应用程序的不同版本写入的文件),可将 VERSIONABLE_SCHEMA 值作为 IMPLEMENT_SERIAL 宏的参数。有关用法信息和示例,请参见 CArchive 类的 GetObjectSchema 成员函数。以下示例显示了如何将 IMPLEMENT_SERIAL 用于从 CObject 派生的 CPerson 类。IMPLEMENT_SERIAL( CPerson, CObject, 1 )
正如序列化:序列化对象文章中所讨论的,一旦具有可序列化的类,就可以序列化类的对象。
#undef AFX_API
#define AFX_API AFX_EXT_CLASSclass CStores : public CObject
{
public:
CStores();
virtual ~CStores();
public:
//DECLARE_SERIAL( CStores );
void Serialize( CArchive& archive );
CString m_name;
WORD m_number;public:
double thismonth_water;
public:
double thismonth_eletricity;
public:
double thismonth_gas;
public:
double precedingmonth_water;
public:
double precedingmonth_eletricity;
public:
double precedingmonth_gas;
public:
double fee_water;
public:
double fee_eletricity;
public:
double fee_gas;
public:
double money_water;
public:
double money_eletricity;
public:
double money_gas;
public:
int date_time;
};#undef AFX_API
#define AFX_API
\\\\\\\\\\\\\\\\\\\\
实现
CStores::CStores()
{
thismonth_water=0;
thismonth_eletricity=0;
thismonth_gas=0;
precedingmonth_water=0;
precedingmonth_eletricity=0;
precedingmonth_gas=0;
fee_water=0;
fee_eletricity=0;
fee_gas=0;
money_water=0;
money_eletricity=0;
money_gas=0;
date_time=0;
}CStores::~CStores()
{
}
// CStores 成员函数
void CStores::Serialize( CArchive& archive )
{
// 先调用基类函数的实现
CObject::Serialize( archive ); // now do the stuff for our specific class
if( archive.IsStoring() )
archive <<date_time<<thismonth_water<<thismonth_eletricity<<thismonth_gas
<<precedingmonth_water<<precedingmonth_eletricity<<precedingmonth_gas
<<fee_water<<fee_eletricity<<fee_gas
<<money_water<<money_eletricity<<money_gas;
else
archive >>date_time>>thismonth_water>>thismonth_eletricity>>thismonth_gas
>>precedingmonth_water>>precedingmonth_eletricity>>precedingmonth_gas
>>fee_water>>fee_eletricity>>fee_gas
>>money_water>>money_eletricity>>money_gas;
}
\\\\\\\\\\\\\\\\\\\\\\
public:
CObArray store_ptrarray;
public:
CStores temp_store;
////////////if(pdlg->DoModal()==IDOK)
{
CFile file(L"data.txt",CFile::modeCreate |CFile::modeWrite );
CArchive ar(&file,CArchive::store);
ar.m_pDocument=NULL;
ar.WriteObject(store_ptrarray.GetAt(store_ptrarray.GetSize()-1));
}
/////////////////////按OK的时候 程序提示试图执行系统不支持操作
XP系统
问题在哪?
CStores();
virtual ~CStores();
public:
//DECLARE_SERIAL( CStores );
void Serialize( CArchive& archive );
下面二个是没用的,结果还是一样的问题
//CString m_name;
//WORD m_number;
//DECLARE_SERIAL( CStores );
这一行,没有这一行就不能序列化;
第二就是Serialize是一个虚函数,你应该用向导自动生成重载,避免输入错误
第三,调用序列化是这样的:
CObject::Serialize(ar);
比如:
temp_store.Serialize(ar);