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

📄 mfc3.php

📁 php网页版的mfc教程 不是十分详细 但是很精练 我是新手不是十分会欣赏
💻 PHP
📖 第 1 页 / 共 3 页
字号:
<P align=justify>CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CPerson)</P>
<P align=justify>//Cperson有一个缺省构造函数</P>
<P align=justify>CObject* pObject = pRuntimeClass-&gt;CreateObject();</P>
<P align=justify>Assert( pObject-&gt;IsKindOf(RUNTIME_CLASS(CPerson)); </P>
<OL>
  <OL>
    <P align=justify>
    <LI><A name=_Toc445888993></A><A name=_Toc445782396></A><A 
    name=_Toc452640892></A><A name=_Toc457298957></A><B>实现CObject特性的机制</B> 
    <P></P>
    <P 
    align=justify>由上,清楚了CObject的结构,也清楚了从CObject派生新类时程序员使用CObject特性的方法。现在来考察这些方法如何利用CObjet的结构,CObject结构如何支持这些方法。</P>
    <P align=justify>首先,要揭示DECLARE_DYNAMIC等宏的内容,然后,分析这些宏的作用。</P>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445888994></A><A name=_Toc445782397></A><A 
      name=_Toc452640893></A><A 
      name=_Toc457298958></A><B>DECLARE_DYNAMIC等宏的定义</B> 
      <P></P></LI></OL></LI></OL></OL>
<P 
align=justify>MFC提供了DECLARE_DYNAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL声明宏的两种定义,分别用于静态链接到MFC 
DLL和动态链接到MFC DLL。对应的实现宏IMPLEMNET_XXXX也有两种定义,但是,这里实现宏就不列举了。</P>
<P align=justify></P>
<P align=justify>MFC对这些宏的定义如下:</P>
<P align=justify>#ifdef _AFXDLL //动态链接到MFC DLL</P>
<P align=justify>#define <B>DECLARE_DYNAMIC</B>(class_name) \</P>
<P align=justify>protected: \</P>
<P align=justify>static CRuntimeClass* PASCAL _GetBaseClass(); \</P>
<P align=justify>public: \</P>
<P align=justify>static const AFX_DATA CRuntimeClass class##class_name; \</P>
<P align=justify>virtual CRuntimeClass* GetRuntimeClass() const; \</P>
<P align=justify></P>
<P align=justify>#define _<B>DECLARE_DYNAMIC</B>(class_name) \</P>
<P align=justify>protected: \</P>
<P align=justify>static CRuntimeClass* PASCAL _GetBaseClass(); \</P>
<P align=justify>public: \</P>
<P align=justify>static AFX_DATA CRuntimeClass class##class_name; \</P>
<P align=justify>virtual CRuntimeClass* GetRuntimeClass() const; \</P>
<P align=justify></P>
<P align=justify>#else</P>
<P align=justify>#define <B>DECLARE_DYNAMIC</B>(class_name) \</P>
<P align=justify>public: \</P>
<P align=justify>static const AFX_DATA CRuntimeClass class##class_name; \</P>
<P align=justify>virtual CRuntimeClass* GetRuntimeClass() const; \</P>
<P align=justify></P>
<P align=justify>#define <B>_DECLARE_DYNAMIC</B>(class_name) \</P>
<P align=justify>public: \</P>
<P align=justify>static AFX_DATA CRuntimeClass class##class_name; \</P>
<P align=justify>virtual CRuntimeClass* GetRuntimeClass() const; \</P>
<P align=justify></P>
<P align=justify>#endif</P>
<P align=justify></P>
<P align=justify>// not serializable, but dynamically constructable</P>
<P align=justify>#define <B>DECLARE_DYNCREATE</B>(class_name) \</P>
<P align=justify>DECLARE_DYNAMIC(class_name) \</P>
<P align=justify>static CObject* PASCAL CreateObject();</P>
<P align=justify></P>
<P align=justify>#define <B>DECLARE_SERIAL</B>(class_name) \</P>
<P align=justify>_DECLARE_DYNCREATE(class_name) \</P>
<P align=justify>friend CArchive&amp; AFXAPI operator&gt;&gt;(CArchive&amp; ar, 
class_name* &amp;pOb);</P>
<P align=justify></P>
<P 
align=justify>由于这些声明宏都是在CObect派生类的定义中被使用的,所以从这些宏的上述定义中可以看出,DECLARE_DYNAMIC宏给所在类添加了一个CRuntimeClass类型的静态数据成员class##class_name(类名加前缀class,例如,若类名是CPerson,则该变量名称是classCPerson),且指定为const;两个(使用MFC 
DLL时,否则,一个)成员函数:虚拟函数GetRuntimeClass和静态函数_GetBaseClass(使用MFC DLL时)。</P>
<P 
align=justify>DECLARE_DYNCREATE宏包含了DECLARE_DYNAMIC,在此基础上,还定义了一个静态成员函数CreateObject。</P>
<P 
align=justify>DECLARE_SERIAL宏则包含了_DECLARE_DYNCREATE,并重载了操作符“&gt;&gt;”(友员函数)。它和前两个宏有所不同的是CRuntimeClass数据成员class##class_name没有被指定为const。</P>
<P align=justify></P>
<P 
align=justify>对应地,MFC使用三个宏初始化DECLARE宏所定义的静态变量并实现DECLARE宏所声明的函数:IMPLEMNET_DYNAMIC,IMPLEMNET_DYNCREATE,IMPLEMENT_SERIAL。</P>
<P 
align=justify>首先,这三个宏初始化CRuntimeClass类型的静态成员变量class#class_name。IMPLEMENT_SERIAL不同于其他两个宏,没有指定该变量为const。初始化内容在下节讨论CRuntimeClass时给出。</P>
<P align=justify>其次,它实现了DECLARE宏声明的成员函数:</P>
<UL>
  <P align=justify>
  <LI>_GetBaseClass() 
  <P></P></LI></UL>
<P align=justify>返回基类的运行时类信息,即基类的CRuntimeClass类型的静态成员变量。这是静态成员函数。</P>
<UL>
  <P align=justify>
  <LI>GetRuntimeClass() 
  <P></P></LI></UL>
<P align=justify>返回类自己的运行类信息,即其CRuntimeClass类型的静态成员变量。这是虚拟成员函数。</P>
<P 
align=justify>对于动态创建宏,还有一个静态成员函数CreateObject,它使用C++操作符和类的缺省构造函数创建本类的一个动态对象。</P>
<UL>
  <P align=justify>
  <LI>操作符的重载 
  <P></P></LI></UL>
<P align=justify>对于序列化的实现宏IMPLEMENT_SERIAL,还重载了操作符&lt;&lt;和定义了一个静态成员变量</P>
<P align=justify>static const AFX_CLASSINIT 
_init_##class_name(RUNTIME_CLASS(class_name)); </P>
<P 
align=justify>比如,对CPerson来说,该变量是_init_Cperson,其目的在于静态成员在应用程序启动之前被初始化,使得AFX_CLASSINIT类的构造函数被调用,从而通过AFX_CLASSINIT类的构造函数在模块状态的CRuntimeClass链表中插入构造函数参数表示的CRuntimeClass类信息。至于模块状态,在后文有详细的讨论。</P>
<P align=justify>重载的操作符函数用来在序列化时从文档中读入该类对象的内容,是一个友员函数。定义如下:</P>
<P align=justify>CArchive&amp; AFXAPI operator&gt;&gt;(CArchive&amp; ar, 
class_name* &amp;pOb) </P>
<P align=justify>{</P>
<P align=justify>pOb = (class_name*) ar.ReadObject(</P>
<P align=justify>RUNTIME_CLASS(class_name));</P>
<P align=justify>return ar;</P>
<P align=justify>}</P>
<P 
align=justify>回顾CObject的定义,它也有一个CRuntimeClass类型的静态成员变量classCObject,因为它本身也支持三个特性。</P>
<P 
align=justify>以CObject及其派生类的静态成员变量classCObject为基础,IsKindOf和动态创建等函数才可以起到作用。</P>
<P 
align=justify>这个变量为什么能有这样的用处,这就要分析CRuntimeClass类型变量的结构和内容了。下面,在讨论了CRuntimeClass的结构之后,考察该类型的静态变量被不同的宏初始化之后的内容。</P>
<OL>
  <OL>
    <OL>
      <P align=justify>
      <LI><A name=_Toc445888995></A><A name=_Toc445782398></A><A 
      name=_Toc452640894></A><A 
      name=_Toc457298959></A><B>CruntimeClass类的结构与功能</B> 
      <P></P></LI></OL></OL></OL>
<P 
align=justify>从上面的讨论可以看出,在对CObject特性的支持上,CRuntimeClass类起到了关键作用。下面,考查它的结构和功能。</P>
<OL>
  <P align=justify>
  <LI>CRuntimeClass的结构 
  <P></P>
  <P align=justify>CruntimeClass的结构如下:</P>
  <P align=justify>Struct CRuntimeClass</P>
  <P align=justify>{</P>
  <P align=justify>LPCSTR m_lpszClassName;//类的名字</P>
  <P align=justify>int m_nObjectSize;//类的大小</P>
  <P align=justify>UINT m_wSchema;</P>
  <P align=justify>CObject* (PASCAL* m_pfnCreateObject)();</P>
  <P align=justify>//pointer to function, equal to newclass.CreateObject() </P>
  <P align=justify>//after IMPLEMENT</P>
  <P align=justify>CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();</P>
  <P align=justify>CRumtieClass* m_pBaseClass;</P>
  <P align=justify></P>
  <P align=justify>//operator:</P>
  <P align=justify>CObject *CreateObject();</P>
  <P align=justify>BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) 
const;</P>
  <P align=justify>...</P>
  <P align=justify>}</P>
  <P 
  align=justify>CRuntimeClass成员变量中有两个是函数指针,还有几个用来保存所在CruntimeClass对象所在类的名字、类的大小(字节数)等。</P>
  <P align=justify>这些成员变量被三个实现宏初始化,例如:</P>
  <P 
  align=justify>m_pfnCreateObject,将被初始化指向所在类的静态成员函数CreateObject。CreateObject函数在初始化时由实现宏定义,见上文的说明。</P>
  <P 
  align=justify>m_pfnGetBaseClass,如果定义了_AFXDLL,则该变量将被初始化指向所在类的成员函数_GetBaseClass。_GetBaseClass在声明宏中声明,在初始化时由实现宏定义,见上文的说明。</P>
  <P 
  align=justify>下面,分析三个宏对CObject及其派生类的CRuntimeClass类型的成员变量class##class_name初始化的情况,然后讨论CRuntimeClass成员函数的实现。</P>
  <P align=justify></P>
  <LI>成员变量class##class_name的内容 
  <P></P>
  <P 
  align=justify>IMPLEMENT_DYNCREATE等宏将初始化类的CRuntimeClass类型静态成员变量的各个域,表3-1列出了在动态类信息、动态创建、序列化这三个不同层次下对该静态成员变量的初始化情况:</P>
  <P align=center>表3-1 静态成员变量class##class_name的初始化</P>
  <TABLE cellSpacing=1 cellPadding=7 width=497 border=1>
    <TBODY>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>CRuntimeClass成员变量 </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>动态类信息 </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>动态创建 </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>序列化 </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_lpszClassName </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类名字符串 </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>类名字符串 </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类名字符串 </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_nObjectSize </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类的大小(字节数) </P></TD>
      <TD vAlign=top width="25%">
        <P align=justify>类的大小(字节数) </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>类的大小(字节数) </P></TD></TR>
    <TR>
      <TD vAlign=top width="27%">
        <P align=justify>m_wShema </P></TD>
      <TD vAlign=top width="24%">
        <P align=justify>0xFFFF </P></TD>
      <TD vAlign=top width="25%">

⌨️ 快捷键说明

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