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

📄 mfc3.php

📁 php网页版的mfc教程 不是十分详细 但是很精练 我是新手不是十分会欣赏
💻 PHP
📖 第 1 页 / 共 3 页
字号:
<HTML><HEAD><TITLE>MFC教程_ CObject类</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content="MSHTML 6.00.2800.1458" name=GENERATOR></HEAD>
<BODY bgColor=#ffffff>
<OL start=3>
  <P align=justify>
  <LI><A name=_Toc445782393></A><A name=_Toc452640889></A><A 
  name=_Toc457298954></A><B>CObject类</B> 
  <P></P>
  <P 
  align=justify>CObject是大多数MFC类的根类或基类。CObject类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,等等。MFC从CObject派生出许多类,具备其中的一个或者多个特性。程序员也可以从CObject类派生出自己的类,利用CObject类的这些特性。</P>
  <P 
  align=justify>本章将讨论MFC如何设计CObject类的这些特性。首先,考察CObject类的定义,分析其结构和方法(成员变量和成员函数)对CObject特性的支持。然后,讨论CObject特性及其实现机制。</P>
  <OL>
    <P align=justify>
    <LI><A name=_Toc445888991></A><A name=_Toc445782394></A><A 
    name=_Toc452640890></A><A name=_Toc457298955></A><B>CObject的结构</B> 
    <P></P>
    <P align=justify>以下是CObject类的定义:</P>
    <P align=justify>class CObject</P>
    <P align=justify>{</P>
    <P align=justify>public:</P>
    <P align=justify></P>
    <P align=justify>//与动态创建相关的函数</P>
    <P align=justify>virtual CRuntimeClass* GetRuntimeClass() const;</P>
    <P align=justify>析构函数</P>
    <P align=justify>virtual ~CObject(); // virtual destructors are 
necessary</P>
    <P align=justify></P>
    <P align=justify>//与构造函数相关的内存分配函数,可以用于DEBUG下输出诊断信息</P>
    <P align=justify>void* PASCAL operator new(size_t nSize);</P>
    <P align=justify>void* PASCAL operator new(size_t, void* p);</P>
    <P align=justify>void PASCAL operator delete(void* p);</P>
    <P align=justify>#if defined(_DEBUG) &amp;&amp; 
    !defined(_AFX_NO_DEBUG_CRT)</P>
    <P align=justify>void* PASCAL operator new(size_t nSize, LPCSTR 
    lpszFileName, int nLine);</P>
    <P align=justify>#endif</P>
    <P align=justify></P>
    <P align=justify>//缺省情况下,复制构造函数和赋值构造函数是不可用的</P>
    <P align=justify>//如果程序员通过传值或者赋值来传递对象,将得到一个编译错误</P>
    <P align=justify>protected:</P>
    <P align=justify>//缺省构造函数</P>
    <P align=justify>CObject();</P>
    <P align=justify>private:</P>
    <P align=justify>//复制构造函数,私有</P>
    <P align=justify>CObject(const CObject&amp; objectSrc); // no 
    implementation</P>
    <P align=justify>//赋值构造函数,私有</P>
    <P align=justify>void operator=(const CObject&amp; objectSrc); // no 
    implementation</P>
    <P align=justify></P>
    <P align=justify>// Attributes</P>
    <P align=justify>public:</P>
    <P align=justify>//与运行时类信息、串行化相关的函数</P>
    <P align=justify>BOOL IsSerializable() const;</P>
    <P align=justify>BOOL IsKindOf(const CRuntimeClass* pClass) const;</P>
    <P align=justify>// Overridables</P>
    <P align=justify>virtual void Serialize(CArchive&amp; ar);</P>
    <P align=justify>// 诊断函数</P>
    <P align=justify>virtual void AssertValid() const;</P>
    <P align=justify>virtual void Dump(CDumpContext&amp; dc) const;</P>
    <P align=justify></P>
    <P align=justify>// Implementation</P>
    <P align=justify>public:</P>
    <P align=justify>//与动态创建对象相关的函数</P>
    <P align=justify>static const AFX_DATA CRuntimeClass classCObject;</P>
    <P align=justify>#ifdef _AFXDLL</P>
    <P align=justify>static CRuntimeClass* PASCAL _GetBaseClass();</P>
    <P align=justify>#endif</P>
    <P align=justify>};</P>
    <P align=justify></P>
    <P align=justify>由上可以看出,CObject定义了一个CRuntimeClass类型的静态成员变量:</P>
    <P align=justify>CRuntimeClass classCObject</P>
    <P align=justify>还定义了几组函数:</P>
    <P align=justify>构造函数析构函数类,</P>
    <P align=justify>诊断函数,</P>
    <P align=justify>与运行时类信息相关的函数,</P>
    <P align=justify>与串行化相关的函数。</P>
    <P 
    align=justify>其中,一个静态函数:_GetBaseClass;五个虚拟函数:析构函数、GetRuntimeClass、Serialize、AssertValid、Dump。这些虚拟函数,在CObject的派生类中应该有更具体的实现。必要的话,派生类实现它们时可能要求先调用基类的实现,例如Serialize和Dump就要求这样。</P>
    <P align=justify>静态成员变量classCObject和相关函数实现了对CObjet特性的支持。</P>
    <P align=justify></P>
    <LI><A name=_Toc445888992></A><A name=_Toc445782395></A><A 
    name=_Toc452640891></A><A name=_Toc457298956></A><B>CObject类的特性</B> 
    <P></P></LI></OL></LI></OL>
<P align=justify>下面,对三种特性分别描述,并说明程序员在派生类中支持这些特性的方法。</P>
<OL>
  <P align=justify>
  <LI>对运行时类信息的支持 
  <P></P></LI></OL>
<P 
align=justify>该特性用于在运行时确定一个对象是否属于一特定类(是该类的实例),或者从一个特定类派生来的。CObject提供IsKindOf函数来实现这个功能。</P>
<P align=justify>从CObject派生的类要具有这样的特性,需要:</P>
<UL>
  <P align=justify>
  <LI>定义该类时,在类说明中使用DECLARE_DYNAMIC(CLASSNMAE)宏; 
  <P></P>
  <P align=justify></P>
  <LI>在类的实现文件中使用IMPLEMENT_DYNAMIC(CLASSNAME,BASECLASS)宏。 
  <P></P></LI></UL>
<P align=justify></P>
<OL>
  <P align=justify>
  <LI>对动态创建的支持 
  <P></P></LI></OL>
<P 
align=justify>前面提到了动态创建的概念,就是运行时创建指定类的实例。在MFC中大量使用,如前所述框架窗口对象、视对象,还有文档对象都需要由文档模板类(CDocTemplate)对象来动态的创建。</P>
<P align=justify>从CObject派生的类要具有动态创建的功能,需要:</P>
<UL>
  <P align=justify>
  <LI>定义该类时,在类说明中使用DECLARE_DYNCREATE(CLASSNMAE)宏; 
  <P></P>
  <P align=justify></P>
  <LI>定义一个不带参数的构造函数(默认构造函数); 
  <P></P>
  <P align=justify></P>
  <LI>在类的实现文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏; 
  <P></P>
  <P align=justify></P>
  <LI>使用时先通过宏RUNTIME_CLASS得到类的RunTime信息,然后使用CRuntimeClass的成员函数CreateObject创建一个该类的实例。 

  <P></P></LI></UL>
<P align=justify>例如:</P>
<P align=justify>CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CNname)</P>
<P align=justify>//CName必须有一个缺省构造函数</P>
<P align=justify>CObject* pObject = pRuntimeClass-&gt;CreateObject();</P>
<P align=justify>//用IsKindOf检测是否是CName类的实例</P>
<P align=justify>Assert( pObject-&gt;IsKindOf(RUNTIME_CLASS(CName));</P>
<P align=justify></P>
<OL>
  <P align=justify>
  <LI>对序列化的支持 
  <P></P></LI></OL>
<DIR>
<P 
align=justify>“序列化”就是把对象内容存入一个文件或从一个文件中读取对象内容的过程。从CObject派生的类要具有序列化的功能,需要:</P></DIR>
<UL>
  <P align=justify>
  <LI>定义该类时,在类说明中使用DECLARE_SERIAL(CLASSNMAE)宏; 
  <P></P>
  <P align=justify></P>
  <LI>定义一个不带参数的构造函数(默认构造函数); 
  <P></P>
  <P align=justify></P>
  <LI>在类的实现文件中使用IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)宏; 
  <P></P>
  <P align=justify></P>
  <LI>覆盖Serialize成员函数。(如果直接调用Serialize函数进行序列化读写,可以省略前面三步。) 
  <P></P></LI></UL>
<P align=justify></P>
<P 
align=justify>对运行时类信息的支持、动态创建的支持、串行化的支持层(不包括直接调用Serailize实现序列化),这三种功能的层次依次升高。如果对后面的功能支持,必定对前面的功能支持。支持动态创建的话,必定支持运行时类信息;支持序列化,必定支持前面的两个功能,因为它们的声明和实现都是后者包含前者。</P>
<OL>
  <P align=justify>
  <LI>综合示例: 
  <P></P></LI></OL>
<P align=justify>定义一个支持串行化的类CPerson:</P>
<P align=justify>class CPerson : public CObject</P>
<P align=justify>{</P>
<DIR>
<P align=justify>public:</P></DIR>
<P align=justify>DECLARE_SERIAL( CPerson )</P>
<P align=justify>// 缺省构造函数</P>
<P align=justify>CPerson(){}{};</P>
<P align=justify></P>
<P align=justify>CString m_name;</P>
<P align=justify>WORD m_number;</P>
<P align=justify></P>
<P align=justify>void Serialize( CArchive&amp; archive );</P>
<P align=justify></P>
<P align=justify>// rest of class declaration</P>
<P align=justify>};</P>
<P align=justify></P>
<P align=justify>实现该类的成员函数Serialize,覆盖CObject的该函数:</P>
<P align=justify>void CPerson::Serialize( CArchive&amp; archive )</P>
<P align=justify>{</P>
<P align=justify>// 先调用基类函数的实现</P>
<P align=justify>CObject::Serialize( archive );</P>
<P align=justify></P>
<P align=justify>// now do the stuff for our specific class</P>
<P align=justify>if( archive.IsStoring() )</P>
<P align=justify>archive &lt;&lt; m_name &lt;&lt; m_number;</P>
<P align=justify>else</P>
<P align=justify>archive &gt;&gt; m_name &gt;&gt; m_number;</P>
<P align=justify>}</P>
<P align=justify></P>
<P align=justify>使用运行时类信息:</P>
<P align=justify>CPerson a; </P>
<P align=justify>ASSERT( a.IsKindOf( RUNTIME_CLASS( CPerson ) ) );</P>
<P align=justify>ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );</P>
<P align=justify>动态创建:</P>

⌨️ 快捷键说明

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