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

📄 mfc3.php

📁 php网页版的mfc教程 不是十分详细 但是很精练 我是新手不是十分会欣赏
💻 PHP
📖 第 1 页 / 共 3 页
字号:
        <P align=justify>0xFFFF </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>1、2等,非0 </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_pfnCreateObject </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>NULL </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>类的成员函数</P>
        <P align=justify>CreateObject </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类的成员函数</P>
        <P align=justify>CreateObject </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_pBaseClass </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>基类的CRuntimeClass变量 </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>基类的CRuntimeClass变量 </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>基类的CRuntimeClass变量 </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_pfnGetBaseClass </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类的成员函数</P>
        <P align=justify>_GetBaseClass </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>类的成员函数</P>
        <P align=justify>_GetBaseClass </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类的成员函数</P>
        <P align=justify>_GetBaseClass </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_pNextClass </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>NULL </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>NULL </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>NULL </P></TD></TR></TBODY></TABLE>
  <P align=center></P>
  <P 
  align=justify>m_wSchema类型是UINT,定义了序列化中保存对象到文档的程序的版本。如果不要求支持序列化特性,该域为0XFFFF,否则,不能为0。</P>
  <P align=justify>Cobject类本身的静态成员变量classCObject被初始化为:</P>
  <P align=justify>{ "CObject", sizeof(CObject), 0xffff, NULL, 
  &amp;CObject::_GetBaseClass, NULL };</P>
  <P align=justify>对初始化内容解释如下:</P>
  <P align=justify>类名字符串是“CObject”,类的大小是sizeof(CObject),不要求支持序列化,不支持动态创建。</P>
  <P align=justify></P>
  <LI>成员函数CreateObject 
  <P></P>
  <P 
  align=justify>回顾3.2节,动态创建对象是通过语句pRuntimeClass-&gt;CreateObject完成的,即调用了CRuntimeClass自己的成员函数,CreateObject函数又调用m_pfnCreateObject指向的函数来完成动态创建任务,如下所示:</P>
  <P align=justify>CObject* CRuntimeClass::CreateObject()</P>
  <P align=justify>{</P>
  <P align=justify>if (m_pfnCreateObject == NULL) //判断函数指针是否空</P>
  <P align=justify>{</P>
  <P align=justify>TRACE(_T("Error: Trying to create object which is not ")</P>
  <P align=justify>_T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),</P>
  <P align=justify>m_lpszClassName);</P>
  <P align=justify>return NULL;</P>
  <P align=justify>}</P>
  <P align=justify>//函数指针非空,继续处理</P>
  <P align=justify>CObject* pObject = NULL;</P>
  <P align=justify>TRY</P>
  <P align=justify>{</P>
  <P align=justify>pObject = (*m_pfnCreateObject)(); //动态创建对象</P>
  <P align=justify>}</P>
  <P align=justify>END_TRY</P>
  <P align=justify>return pObject;</P>
  <P align=justify>}</P>
  <P align=justify></P>
  <P align=justify></P>
  <LI>成员函数IsDerivedFrom 
  <P></P>
  <P 
  align=justify>该函数用来帮助运行时判定一个类是否派生于另一个类,被CObject的成员函数IsKindOf函数所调用。其实现描述如下:</P>
  <P 
  align=justify>如果定义了_AFXDLL则,成员函数IsDerivedFrom调用成员函数m_pfnGetBaseClass指向的函数来向上逐层得到基类的CRuntimeClass类型的静态成员变量,直到某个基类的CRuntimeClass类型的静态成员变量和参数指定的CRuntimeClass变量一致或者追寻到最上层为止。</P>
  <P 
  align=justify>如果没有定义_AFXDLL,则使用成员变量m_pBaseClass基类的CRuntimeClass类型的静态成员变量。</P>
  <P align=justify>程序如下所示:</P>
  <P align=justify>BOOL CRuntimeClass::IsDerivedFrom(</P>
  <P align=justify>const CRuntimeClass* pBaseClass) const</P>
  <P align=justify>{</P>
  <P align=justify>ASSERT(this != NULL);</P>
  <P align=justify>ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), 
  FALSE));</P>
  <P align=justify>ASSERT(pBaseClass != NULL);</P>
  <P align=justify>ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), 
  FALSE));</P>
  <P align=justify></P>
  <P align=justify>// simple SI case</P>
  <P align=justify>const CRuntimeClass* pClassThis = this;</P>
  <P align=justify>while (pClassThis != NULL)//从本类开始向上逐个基类搜索</P>
  <P align=justify>{</P>
  <P align=justify>if (pClassThis == pBaseClass)//若是参数指定的类信息</P>
  <P align=justify>return TRUE;</P>
  <P align=justify>//类信息不符合,继续向基类搜索</P>
  <P align=justify>#ifdef _AFXDLL</P>
  <P align=justify>pClassThis = (*pClassThis-&gt;m_pfnGetBaseClass)();</P>
  <P align=justify>#else</P>
  <P align=justify>pClassThis = pClassThis-&gt;m_pBaseClass;</P>
  <P align=justify>#endif</P>
  <P align=justify>}</P>
  <P align=justify>return FALSE; // 搜索完毕,没有匹配,返回FALSE。</P>
  <P align=justify>}</P>
  <P 
  align=justify>由于CRuntimeClass类型的成员变量是静态成员变量,所以如果两个类的CruntimeClass成员变量相同,必定是同一个类。这就是IsDerivedFrom和IsKindOf的实现基础。</P>
  <P align=justify></P>
  <LI>RUNTIME_CLASS宏 
  <P></P></LI></OL>
<DIR>
<P align=justify>RUNTIME_CLASS宏定义如下:</P>
<P>#define RUNTIME_CLASS(class_name) 
(&amp;class_name::class##class_name)</P></DIR>
<P 
align=justify>为了方便地得到每个类(Cobject或其派生类)的CRuntimeClass类型的静态成员变量,MFC定义了这个宏。它返回对类class_name的CRuntimeClass类型成员变量的引用,该成员变量的名称是“class”加上class_name(类的名字)。例如:</P>
<P align=justify>RUNTIME_CLASS(CObject)得到对classCObject的引用;</P>
<P align=justify>RUNTIME_CLASS(CPerson)得到对class CPerson的引用。</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445888996></A><A name=_Toc445782399></A><A 
      name=_Toc452640895></A><A name=_Toc457298960></A><B>动态类信息、动态创建的原理</B> 
      <P></P></LI></OL></OL></OL>
<DIR>
<P align=justify>MFC对Cobject动态类信息、动态创建的实现原理:</P></DIR>
<P align=justify>动态类信息、动态创建都建立在给类添加的CRuntimeClass类型的静态成员变量基础上,总结如下。</P>
<P 
align=justify>C++不支持动态创建,但是支持动态对象的创建。动态创建归根到底是创建动态对象,因为从一个类名创建一个该类的实例最终是创建一个以该类为类型的动态对象。其中的关键是从一个类名可以得到创建其动态对象的代码。</P>
<P align=justify>在一个类没有任何实例之前,怎么可以得到该类的创建动态对象的代码?借助于C++的静态成员数据技术可达到这个目的:</P>
<UL>
  <P align=justify>
  <LI>静态成员数据在程序的入口(main或WinMain)之前初始化。因此,在一个静态成员数据里存放有关类型信息、动态创建函数等,需要的时候,得到这个成员数据就可以了。 

  <P></P>
  <P align=justify></P>
  <LI>不论一个类创建多少实例,静态成员数据只有一份。所有的类的实例共享一个静态成员数据,要判断一个类是否是一个类的实例,只须确认它是否使用了该类的这个静态数据。 

  <P></P></LI></UL>
<P 
align=justify>从前两节的讨论知道,DECLARE_CREATE等宏定义了一个这样的静态成员变量:类型是CRuntimeClass,命名约定是“calss”加上类名;IMPLEMENT_CREATE等宏初始化该变量;RUNTIME_CLASS宏用来得到该成员变量。</P>
<P align=justify>动态类信息的原理在分析CRuntimeClass的成员函数IsDerivedFrom时已经作了解释。</P>
<P align=justify>动态创建的过程和原理了,用图表示其过程如下:</P>
<P align=justify></P>
<IMG height=208 hspace=12 src="image111.gif" 
width=421 align=left> 
<P align=justify>注:下面一个方框内的逐级缩进表示逐层调用关系。</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445888997></A><A name=_Toc445782400></A><A 
      name=_Toc452640896></A><A name=_Toc457298961></A><B>序列化的机制</B> 
      <P></P></LI></OL></OL></OL>
<P 
align=justify>由上所述可知,一个类要支持实现序列化,使得它的对象可以保存到文档中或者可以从文档中读入到内存中并生成对象,需要使用动态类信息,而且,需要覆盖基类的Serialize虚拟函数来完成其对象的序列化。</P>
<P align=justify>仅仅有类的支持是不够的,MFC还提供了一个归档类CArchive来支持简单类型的数据和复杂对象的读写。</P>
<P align=justify>CArchive 
在文件和内存对象之间充当一个代理者的角色。它负责按一定的顺序和格式把内存对象写到文件中,或者读出来,可以被看作是一个二进制的流。它和文件类CFile的关系如图3-2所示:</P>
<IMG 
height=218 hspace=12 src="image112.gif" width=312 align=left> 
<P align=justify></P>
<P align=justify>一个CArchive对象在要序列化的对象和存储媒体(storage 
medium,可以是一个文件或者一个Socket)之间起了中介作用。它提供了系列方法来完成序列化,不仅能够把int、float等简单类型数据进行序列化,而且能够把复杂的数据如string等进行序列化,更重要的是它能把复杂的对象(包括复合对象)进行序列化。这些方法就是重载的操作符&gt;&gt;和&lt;&lt;。对于简单类型,它针对不同类型直接实现不同的读写操作;对于复杂的对象,其每一个支持序列化的类都重载了操作符&gt;&gt;,从前几节可以清楚地看到这点:IMPLEMENT_SERIAL给所在类重载了操作符&gt;&gt;。至于&lt;&lt;操作,就不必每个序列化类都重载了。</P>
<P 
align=justify>复杂对象的“&lt;&lt;”操作,先搜索本模块状态的CRuntimeClass链表看是否有“&lt;&lt;”第二个参数指定的对象类的运行类信息(搜索过程涉及到模块状态,将在9.5.2节描述),如果有(无,则返回),则先使用这些信息动态的创建对象(这就是是序列化类必须提供动态类信息、支持动态创建的原因),然后对该对象调用Serilize函数从存储媒体读入对象内容。</P>
<P 
align=justify>复杂对象的“&gt;&gt;”操作先把对象类的运行类信息写入存储媒体,然后对该对象调用Serilize函数把对象内容写入存储媒体。</P>
<P 
align=justify>在创建CArchive对象时,必须有一个CFile对象,它代表了存储媒介。通常,程序员不必做这个工作,打开或保存文档时MFC将自动的创建CFile对象和CArchive对象并在适当的时候调用序列化类的Serialize函数。在后面讨论打开(5.3.3.2节)或者关闭(6.1节)文档时将会看到这样的流程。</P>
<P 
align=justify>CArchive对象被创建时,需要指定它是用来读还是用来写,即指定序列化操作的方向。Serialize函数适用CArchive的函数IsStoring判定CArchive是用于读出数据还是写入数据。</P>
<P align=justify></P>
<P 
align=justify>在解释实现序列化的方法时,曾经提到如果程序员直接调用Serilize函数完成序列化,而不借助CArchive的&gt;&gt;和&lt;&lt;操作,则可以不需要动态类信息和动态创建。从上文的论述可以看出,没有CArchive的&gt;&gt;和&lt;&lt;操作,的确不需要动态类信息和动态创建特性。</P>
<hr>
<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
  <tr>
    <td align="center"><a href="mfc2.php" target="_self">上一章</a> <a href="mfc.php" target="_self">回目录</a> <a href="mfc4.php" target="_self">下一章</a></td>
  </tr>
</table>
<p>&nbsp;</p>
<P align=justify></P>
</BODY></HTML>

⌨️ 快捷键说明

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