一、线性化函数(串行化函数)------CObject::Serialize功能:从档案文件中读取该对象或者向档案文件中写入该对象必须为希望串行化的每个类重载Serialize函数,被重载的Serialize函数首先必须调用基类的Serialize函数。在类的声明中必须使用DECLARE_SERYAL宏,并且在类的执行过程中必须使用IMPLEMENT_SERIAL宏IMPLEMENT_SERIAL二、IMPLEMENT_SERIAL(class_name,base_class_name,wSchema)参数:class_name类的实际名字(不用引号括起来)。base_class_name基类的名字(不用引号括起来)。wSchema一个UINT类型的版本号,将被用在存档中,使得解串行程序能够识别并处理早期版本的程序所生成的数据。它的值不能是-1,一般是大于等于0的整数。说明:这个宏为动态的CObject派生类对象生成必要的C++代码,使它能够在运行时访问类名及其在继承关系中的位置。在.CPP模块中使用IMPLEMENT_SERIAL宏,然后一次性地连接生成的目标代码。如果磁盘文件上的对象的版本号和内存中的对象的版本号不一致,MFC将抛出一个CArchiveException异常,阻止程序读入一个不匹配版本的对象。例题.从CObject或其派生类派生出用户的类2.重载Serialize()成员函数,加入必要的代码,用以保存对象的数据成员到CArchive对象以及从CArchive对象载入对象的数据成员状态。3.在类声明文件中,加入DECLARE_SERIAL宏。编译时,编译器将扩充该宏,这是串行化对象所必需的。4.定义一个不带参数的构造函数。5.在实现文件中加入IMPLEMENT_SERIAL宏。classCRegister:publicCObject{public:DECLARE_SERIAL(CRegister)//必需提供一个不带任何参数的空的构造函数CRegister(){};public:CStringstrIncome;CStringstrKind;BOOLbMarried;CStringstrName;intnSex;CStringstrUnit;intnWork;UINTnAge;voidSerialize(CArchive&);};MFC在从磁盘文件载入对象状态并重建对象时,需要有一个缺省的不带任何参数的构造函数。串行化对象将用该构造函数生成一个对象,然后调用Serialize()函数,用重建对象所需的值来填充对象的所有数据成员变量。构造函数可以声明为public、protected或private。如果使它成为protect或private,则可以确保它只被串行化过程所使用。在类定义文件中给出Serialize()的定义。它包括对象的保存和载入两部分。前面已经提到,CArchive类提供一个IsStoring()成员函数指示是保存数据到磁盘文件还是从磁盘文件载入对象。voidCRegister::Serialize(CArchive&ar){//首先调用基类的Serialize()方法。CObject::Serialize(ar);if(ar.IsStoring()){arstrIncome;arstrKind;ar(int)bMarried;arstrName;arnSez;arstrUnit;arnWork;ar(WORD)nAge;}else{arstrIncome;arstrKind;ar(int)bMarried;arstrName;arnSex;arstrUnit;arnWork;ar(WORD)nAge;}}我们看到,对象的串行化实际上是通过调用对象中的数据成员的串行化来完成的。注意:CArchive类的和操作符并不支持所有的标准数据类型。它支持的数据类型有:CObject、BYTE、WORD、int、LONG、DWORD、float和double。其他的类型的数据要进行串行化输入输出时,需要将该类型的数据转化为上述几种类型之一方可。另外,在类的实现(类定义)文件开始处,还要加入IMPLEMENT_SERIAL宏。IMPLEMENT_SERIAL(CRegister,CObject,1)IMPLEMENT_SERIAL宏用于定义一个从CObject派生的可串行化类的各种函数。宏的第一和第二个参数分别代表可串行化的类名和该类的直接基类。第三个参数是对象的版本号,它是一个大于或等于零的整数。MFC串行化代码在将对象读入内存时检查版本号。如果磁盘文件上的对象的版本号和内存中的对象的版本号不一致,MFC将抛出一个CArchiveException异常,阻止程序读入一个不匹配版本的对象。现在,我们就可以象使用标准MFC类一样使用CRegister的串行化功能了。CArchivear;CRegisterreg1,reg2;arreg1reg2;串行化简化了对象的保存和载入,为对象提供了持续性。但是,串行化本身还是具有一定的局限性的。串行化一次从文件中载入所有对象,这不适合于大文件编辑器和数据库。对于数据库和大文件编辑器,它们每次只是从文件中读入一部分。此时,就要避开文档的串行化机制来直接读取和保存文件了。另外,使用外部文件格式(预先定义的文件格式而不是本应用程序定义的文件格式)的程序一般也不使用文档的串行化。《VC++程序设计》试卷模板一、单项选择题(每小题1分,共20分)1、假定AB为一个类,则执行“”ABa(4),b(3),*p[2];”语句时,自动调用该类构造函数的次数为(b)A、2B、3C、4D、52、对于结构中定义的成员,其隐含访问权限为(c)A、protectedB、privateC、publicD、static3、在面向对象编程中,对象的抽象集合称为(c)。A、对象B、集合C、类D、实例4、下面说法正确的是(a)A、构造函数可以重载,析构函数不能重载。B、构造函数不能重载,析构函数可以重载。C、构造函数可以重载,析构函数也可以重载。D、构造函数和析构函数都不可以重载。5、实现运行时的多态性,必须通过(a)来完成。A、虚函数B、重载函数C、构造函数D、析构函数6、类CNum的缺省构造函数和析构函数是(a)A、CNum()和~CNum()B、CNum(int)和~CNum()C、CNum()和~CNum(delete)D、CNum()和int~CNum()7、在类外定义类的成员函数时,应当使用(b)来标识该函数为特定类的成员。A、:B、::C、-D、this8、已知类A是类B的友元,类B是类C的友元,则(d)A、类A一定是类C的友元B、类C一定是类A的友元C、类C的成员函数可以访问类B的对象的任何成员D、类A的成员函数可以访问类B的对象的任何成员9、下面(a)是函数重载。A、voidplay(int)和voidplay(float)B、play()和~play()C、voidplay(int)和intplay(int)D、voidplay()和intplay()10、下列说法中正确的是(b)A.类定义中只能说明函数成员的函数头,不能定义函数体。B.类中的函数成员可以在类体中定义,也可以在类体之外定义。C.类中的函数成员在类体之外定义时必须要与类声明在同一文件中。D.在类体之外定义的函数成员不能操作该类的私有数据成员。11、Windows操作系统主要基本内核元件中,____b___支持与操作系统密切相关的功能:如进程加载、文本切换、文件I/O以及内存管理、线程管理等。()A、GDIB、KERNELC、USERD、以上都不是。12、一个视图对象能连接(a)文档对象,一个文档对象能连接()视图对象。A、一个,多个B、多个,一个C、一个,一个D、多个,多个13、所有的控件都是(b)类的派生类,都可以作为一个特殊的窗口来处理。A、CViewB、CWndC、CWindowD、CDialog14、设置编辑控件的文本内容,可使用函数(a)A、SetWindowText()B、SetSel()C、ReplaceSel()D、GetWindowText()15、根据对话框的行为性质,对话框可以分为两类:(b)A、对话框资源和对话框类B、模式对话框和非模式对话框C、对话框资源和对话框模板D、消息对话框和模式对话框16、以下控件中,(c)没有Caption属性。A、按钮B、群组框C、编辑控件D、静态控件17、菜单项助记符前用(b)引导。A、%B、&C、#D、$18、MFC中的集合类包括(c)。A、对象、列表和映射B、数组、列表和对象C、数组、列表和映射D、数组、列表和链表19、文档负责将数据存储到永久存储介质中,通常是磁盘文件或数据库,存取过程称为(b)。A、文件访问B、串行化C、文件读写D、格式化20、下列对模板的声明,正确的是(d)。A、templateTB、templateclassT1;classT2C、templateclassT1,T2D、templateclassT1,classT2二、选择填空题(每空1分,共20分)1、如果在基类和派生类中都包含其他类的对象(即有对象成员),则在创建派生类的对象时,首先执行⑴a的构造函数,接着执行⑵c的构造函数,然后执行___⑶_b__的构造函数,最后才执行⑷d的构造函数。A、基类的对象成员B、派生类的对象成员C、基类D、派生类2、所有的文档类都派生于[5]c,所有的视图类都派生于[6]a。A、CViewB、CWindowC、CDocumentD、CFormView3、[7]c包括键盘和鼠标的输入。这一类消息首先放在系统消息队列中,然后由Windows将它们送入应用程序消息队列中,由程序来处理消息;d[8]用来与Windows的控制对象,如列表框、按钮、复选框等进行双向通信。当用户在列表框中改动当前选择或改变了复选框的状态时发出此类消息。A、系统消息B、用户消息C、输入消息D、控制消息4、使用[9]b获取的设备上下文在退出时,必须调用ReleaseDC()释放设备上下文。A、GetWindowRect()B、GetDC()C、BeginPaint()D、GetClientRect()5、常用的CButton类的成员函数中:⑽a获得一个按钮控件的选中、选择和聚焦状态;⑾d得到一个按钮的选中状态;⑿c设置一个按钮的选中状态。A、GetState()B、SetState()C、SetCheck()D、GetCheck()E、GetButtonStyle()6、滚动条类CScrollBar的成员函数规定了滚动条的操作。设置滚动条的范围使用⒀c函数,设置滚动块的位置使用⒁e函数,获取滚动块的当前位置使用⒂f函数。A、SetPosB、SetRangeC、SetScrollRangeD、GetPosE、SetScrollPosF、GetScrollPosG、GetScrollRange7、如果类中的成员只能被本类的成员函数和友元函数访问,则这些成员的访问权限为___[16]b_;如果类中的成员能够被类外的函数访问,则这些成员的访问权限为:___[17]_c_。A、protectedB、privateC、publicD、static8、列表框分为[18]b和[19]c两种,[20]b中任一时刻只能选择一项。A、组合框B、单选列表框C、多选列表框D、编辑框三、程序设计题(共60分)1、下列shape类是一个表示形状的抽象类,area()为求图形面积的函数,total()则是一个通用的用以求不同形状的图形面积总和的函数。请从shape类派生三角形类(triangle)、矩形类(rectangle)、并给出具体的求面积函数。(10分)classshape{public:virtualfloatarea()=0};floattotal(shape*s[],intn){floatsu