⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch13.htm

📁 VC 21天 学习VC 的好东西
💻 HTM
📖 第 1 页 / 共 5 页
字号:
variables. Along with adding the methods to set and read all of the variables, you
need to make the class serializable by adding the Serialize function to the class,
as well as the two macros that complete the serialization of the class.</P>
<P>
<H4>Creating the Basic Class</H4>
<P>As you may remember from Day 10, when you want to create a new class, you can
select the project in the Class View tab of the workspace pane, right-click the mouse
button, and select New Class from the context menu. This opens the New Class dialog.</P>
<P>In the New Class dialog, you specify the type of class, whether it's an MFC class,
and generic class, or a form class. To create a class that can contain one record's
data, you most likely want to create a generic class. You'll learn more about how
to determine which of these types of classes to create on Day 16, &quot;Creating
Your Own Classes and Modules.&quot; The other things that you need to do are give
your class a name and specify the base class from which it will be inherited.</P>
<P>For your sample application, because the form that you created has information
about a person, you might want to call your class something like CPerson. To be able
to hold your class in the object array, you need to give it CObject as the base class.
Just like on Day 10, the New Class dialog will claim that it cannot find the header
with the base class in it and that you need to add this. Well, it's already included,
so you can ignore this message. (On Day 16, you'll learn when you need to pay attention
to this message.)</P>
<P>Once you create your new class, you'll need to add the variables for holding the
data elements that will be displayed on the screen for the user. Following good object-oriented
design, these variables will all be declared as private variables, where they cannot
be directly manipulated by other classes. The variable types should match the variable
types of the variables that are attached to the window controls in the view class.</P>
<P>With the sample application you are creating, you need to add the variables in
Table 13.3.</P>
<P>
<H4>TABLE 13.3. CLASS VARIABLES FOR THE CPerson CLASS.</H4>
<P>
<TABLE BORDER="1">
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">
			<H4>Name
		</TD>
		<TD ALIGN="LEFT">
			<H4>Type
		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">m_bEmployed		</TD>
		<TD ALIGN="LEFT">BOOL		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">m_iAge		</TD>
		<TD ALIGN="LEFT">int		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">m_sName		</TD>
		<TD ALIGN="LEFT">CString		</TD>
	</TR>
	<TR ALIGN="LEFT" VALIGN="TOP">
		<TD ALIGN="LEFT">m_iMaritalStatus		</TD>
		<TD ALIGN="LEFT">int		</TD>
	</TR>
</TABLE>



<BLOCKQUOTE>
	<P>
<HR>
<STRONG>NOTE:</STRONG> An inline function is a short C++ function in which, when the application
	is being compiled, the function body is copied in place of the function call. As
	a result, when the compiled application is running, the function code is executed
	without having to make a context jump to the function and then jump back once the
	function has completed. This reduces the overhead in the running application, increasing
	the execution speed slightly, but also makes the resulting executable application
	slightly larger. The more places the inline function is called, the larger the application
	will eventually get. For more information on inline functions, consult Appendix A,
	&quot;C++ Review.&quot;
<HR>


</BLOCKQUOTE>

<H4>Adding Methods for Reading and Writing Variables</H4>
<P>Once you create your class, you need to provide a means for reading and writing
to the variables in the class. One of the easiest ways to provide this functionality
is to add inline functions to the class definition. You create a set of inline functions
to set each of the variables and then make another set for retrieving the current
value of each variable.</P>
<P>If you want to implement the Get and Set variable functions for your CPerson class
in the sample application that you are building, edit the Person.h header file, adding
the lines in Listing 13.4.</P>
<P>
<H4>LISTING 13.4. THE Get AND Set INLINE FUNCTION DECLARATIONS.</H4>
<PRE> 1: class CPerson : public CObject
 2: {
 3: public:
 4:     // Functions for setting the variables
 5:     void SetEmployed(BOOL bEmployed) { m_bEmployed = bEmployed;}
 6:     void SetMaritalStat(int iStat) { m_iMaritalStatus = iStat;}
 7:     void SetAge(int iAge) { m_iAge = iAge;}
 8:     void SetName(CString sName) { m_sName = sName;}
 9:     // Functions for getting the current settings of the variables
10:     BOOL GetEmployed() { return m_bEmployed;}
11:     int GetMaritalStatus() { return m_iMaritalStatus;}
12:     int GetAge() {return m_iAge;}
13:     CString GetName() {return m_sName;}
14:     CPerson();
15:     virtual ~CPerson();
16: 
17: private:
18:     BOOL m_bEmployed;
19:     int m_iMaritalStatus;
20:     int m_iAge;
21:     CString m_sName;
22: };</PRE>
<P>After you have the methods for setting and retrieving the values of the variables
in your custom class, you'll probably want to make sure that the variables are initialized
when the class is first created. You can do this in the class constructor by setting
each of the variables to a default value. For instance, in your sample application,
you add the code in Listing 13.5 to the constructor of the CPerson class.</P>
<P>
<H4>LISTING 13.5. THE CPerson CONSTRUCTOR.</H4>
<PRE>1: CPerson::CPerson()
2: {
3:     // Initialize the class variables
4:     m_iMaritalStatus = 0;
5:     m_iAge = 0;
6:     m_bEmployed = FALSE;
7:     m_sName = &quot;&quot;;
8: }</PRE>
<P>
<H4>Serializing the Class</H4>
<P>After you have your custom class with all variables defined and initialized, you
need to make the class serializable. Making your class serializable involves three
steps. The first step is adding the Serialize function to the class. This function
writes the variable values to, and reads them back from, the CArchive object using
C++ streams. The other two steps consist of adding the DECLARE_SERIAL and IMPLEMENT_SERIAL
macros. Once you add these elements, your custom class will be serializable and ready
for your application.</P>
<P>To add the Serialize function to your custom class, add a member function through
the Class View tab in the workspace pane. Specify the function type as void, the
function declaration as Serialize(CArchive &amp;ar), and the access as public and
check the Virtual check box. This should add the Serialize function and place you
in the editor, ready to flesh out the function code.</P>
<P>In the Serialize function, the first thing you want to do is to call the ancestor's
Serialize function. When you call the ancestor's function first, any foundation information
that has been saved is restored first, providing the necessary support for your class
before the variables in your class are restored. Once you call the ancestor function,
you need to determine whether you need to read or write the class variables. You
can do this by calling CArchive's IsStoring method. This function returns TRUE if
the archive is being written to and FALSE if it's being read from. If the IsStoring
function returns TRUE, you can use C++ I/O streams to write all your class variables
to the archive. If the function returns FALSE, you can use C++ streams to read from
the archive. In both cases, you must be certain to order the variables in the same
order for both reading and writing. If you need more information about C++ streams,
see Appendix A.</P>
<P>An example of a typical Serialize function for your sample custom class is shown
in Listing 13.6. Notice that the CPerson variables are in the same order when writing
to and reading from the archive.</P>
<P>
<H4>LISTING 13.6. THE CPerson.Serialize FUNCTION.</H4>
<PRE> 1: void CPerson::Serialize(CArchive &amp;ar)
 2: {
 3:     // Call the ancestor function
 4:     CObject::Serialize(ar);
 5: 
 6:     // Are we writing?
 7:     if (ar.IsStoring())
 8:         // Write all of the variables, in order
 9:         ar &lt;&lt; m_sName &lt;&lt; m_iAge &lt;&lt; m_iMaritalStatus &lt;&lt; m_bEmployed;
10:     else
11:         // Read all of the variables, in order
12:         ar &gt;&gt; m_sName &gt;&gt; m_iAge &gt;&gt; m_iMaritalStatus &gt;&gt; m_bEmployed;
13: }</PRE>
<P>Once you have the Serialize function in place, you need to add the macros to your
custom class. The first macro, DECLARE_SERIAL, needs to go in the class header and
is passed the class name as its only argument.</P>
<P>For example, to add the DECLARE_SERIAL macro to the custom CPerson class in your
sample application, you add the macro just below the start of the class declaration,
where it will receive the default access for the class. You specify the class name,
CPerson, as the only argument to the macro, as in Listing 13.7.</P>


<BLOCKQUOTE>
	<P>
<HR>
<STRONG>NOTE:</STRONG> The default access permission for functions and variables in C++
	classes is public. All functions and variables that are declared before the first
	access declaration are public by default. You could easily add all of the public
	class functions and variables in this area of the class declaration, but explicitly
	declaring the access permission for all functions and variables is better practice--because
	that way, there is little to no confusion about the visibility of any of the class
	functions or variables.
<HR>
<BR>
	</P>

	<P>
<HR>
<STRONG>NOTE:</STRONG> Most C++ functions need a semicolon at the end of the line of code.
	The two serialization macros do not, due to the C preprocessor, which replaces each
	of the macros with all of the code before compiling the application. It doesn't hurt
	to place the semicolons there; they are simply ignored.
<HR>


</BLOCKQUOTE>

<H4>LISTING 13.7. THE SERIALIZED CPerson CLASS DECLARATION.</H4>
<PRE> 1: class CPerson : public CObject
 2: {
 3:     DECLARE_SERIAL (CPerson)
 4: public:
 5:     // Functions for setting the variables
 6:     void SetEmployed(BOOL bEmployed) { m_bEmployed = bEmployed;}
 7:     void SetMaritalStat(int iStat) { m_iMaritalStatus = iStat;}
 8:     void SetAge(int iAge) { m_iAge = iAge;}
 9:     void SetName(CString sName) { m_sName = sName;}
10:     // Functions for getting the current settings of the variables
11:     BOOL GetEmployed() { return m_bEmployed;}
12:     int GetMaritalStatus() { return m_iMaritalStatus;}
13:     int GetAge() {return m_iAge;}
14:     CString GetName() {return m_sName;}
15:     CPerson();
16:     virtual ~CPerson();
17: 
18: private:
19:     BOOL m_bEmployed;
20:     int m_iMaritalStatus;
21:     int m_iAge;
22:     CString m_sName;
23: };</PRE>


<BLOCKQUOTE>
	<P>
<HR>
<STRONG>NOTE:</STRONG> In practice, if you read a file that was written using a previous
	version of the Serialize function in your class, your application will raise an exception,
	which you can then catch using standard C++ exception-handling techniques. This allows
	you to add code to your application to recognize and convert files created with earlier
	versions of your application. For information on C++ exception handling, see Appendix
	A.
<HR>


</BLOCKQUOTE>

<P>To complete the serialization of your custom class, you need to add the IMPLEMENT_
SERIAL macro to the class definition. The best place to add this macro is before
the constructor definition in the CPP file containing the class source code. This
macro takes three arguments: the custom class name, the base class name, and the
version number. If you make any changes to the Serialize function, you should increment
the version number argument to the IMPLEMENT_SERIAL macro. This version number indicates
when a file was written using a previous version of the Serialize function and thus
may not be readable by the current version of the application.</P>
<P>To add the IMPLEMENT_SERIAL macro to your sample application, add it into the
Person.cpp file just before the CPerson class constructor. Pass CPerson as the first
argument (the class name), CObject as the second argument (the base class), and 1
as the version number, as in Listing 13.8.</P>
<P>
<H4>LISTING 13.8. THE IMPLEMENT_SERIAL MACRO IN THE CPerson CODE.</H4>
<PRE> 1: // Person.cpp: implementation of the CPerson class.
 2: //
 3: //////////////////////////////////////////////////////////////////////
 4: 
 5: #include &quot;stdafx.h&quot;
 6: #include &quot;Serialize.h&quot;
 7: #include &quot;Person.h&quot;
 8: 
 9: #ifdef _DEBUG
10: #undef THIS_FILE
11: static char THIS_FILE[]=__FILE__;
12: #define new DEBUG_NEW
13: #endif
14: 
15: IMPLEMENT_SERIAL (CPerson, CObject, 1)
16: //////////////////////////////////////////////////////////////////////
17: // Construction/Destruction
18: //////////////////////////////////////////////////////////////////////
19: 
20: CPerson::CPerson()
21: {
22:     // Initialize the class variables
23:     m_iMaritalStatus = 0;
24:     m_iAge = 0;
25:     m_bEmployed = FALSE;
26:     m_sName = &quot;&quot;;
27: }</PRE>
<P>
<H3><A NAME="Heading9"></A>Building Support in the Document Class</H3>
<P>When you build a form-based application, where the form on the window is the primary
place for the user to interact with the application, there is an unstated assumption

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -