标签:MFC const 函数 CRuntimeClass void 深入浅出 CObject 构造函数
MFC深入浅出-CObject类
CObject 是大多数MFC类的根类或基类。CObject类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,等等。MFC从CObject派生出许多类,具备其中的一个或者多个特性。程序员也可以从CObject类派生出自己的类,利用CObject类的这些特性。
本章将讨论 MFC如何设计CObject类的这些特性。首先,考察CObject类的定义,分析其结构和方法(成员变量和成员函数)对CObject特性的支持。然后,讨论CObject特性及其实现机制。
- CObject的结构
以下是 CObject类的定义:
class CObject
{
public:
// 与动态创建相关的函数
virtual CRuntimeClass* GetRuntimeClass() const;
析构函数
virtual ~CObject(); // virtual destructors are necessary
// 与构造函数相关的内存分配函数,可以用于DEBUG下输出诊断信息
void* PASCAL operator new(size_t nSize);
void* PASCAL operator new(size_t, void* p);
void PASCAL operator delete(void* p);
#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)
void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
#endif
// 缺省情况下,复制构造函数和赋值构造函数是不可用的
// 如果程序员通过传值或者赋值来传递对象,将得到一个编译错误
protected:
// 缺省构造函数
CObject();
private:
// 复制构造函数,私有
CObject(const CObject& objectSrc); // no implementation
// 赋值构造函数,私有
void operator=(const CObject& objectSrc); // no implementation
// Attributes
public:
// 与运行时类信息、串行化相关的函数
BOOL IsSerializable() const;
BOOL IsKindOf(const CRuntimeClass* pClass) const;
// Overridables
virtual void Serialize(CArchive& ar);
// 诊断函数
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
// Implementation
public:
// 与动态创建对象相关的函数
static const AFX_DATA CRuntimeClass classCObject;
#ifdef _AFXDLL
static CRuntimeClass* PASCAL _GetBaseClass();
#endif
};
由上可以看出, CObject定义了一个CRuntimeClass类型的静态成员变量:
CRuntimeClass classCObject
还定义了几组函数:
构造函数析构函数类,
诊断函数,
与运行时类信息相关的函数,
与串行化相关的函数。
其中,一个静态函数: _GetBaseClass;五个虚拟函数:析构函数、GetRuntimeClass、Serialize、AssertValid、Dump。这些虚拟函数,在CObject的派生类中应该有更具体的实现。必要的话,派生类实现它们时可能要求先调用基类的实现,例如Serialize和Dump就要求这样。
静态成员变量 classCObject和相关函数实现了对CObjet特性的支持。
- CObject类的特性
下面,对三种特性分别描述,并说明程序员在派生类中支持这些特性的方法。
- 对运行时类信息的支持
该特性用于在运行时确定一个对象是否属于一特定类(是该类的实例),或者从一个特定类派生来的。 CObject提供IsKindOf函数来实现这个功能。
从 CObject派生的类要具有这样的特性,需要:
- 定义该类时,在类说明中使用 DECLARE_DYNAMIC(CLASSNMAE)宏;
- 在类的实现文件中使用 IMPLEMENT_DYNAMIC(CLASSNAME,BASECLASS)宏。
- 对动态创建的支持
前面提到了动态创建的概念,就是运行时创建指定类的实例。在MFC中大量使用,如前所述框架窗口对象、视对象,还有文档对象都需要由文档模板类(CDocTemplate)对象来动态的创建。
从CObject派生的类要具有动态创建的功能,需要:
- 定义该类时,在类说明中使用DECLARE_DYNCREATE(CLASSNMAE)宏;
- 定义一个不带参数的构造函数(默认构造函数);
- 在类的实现文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏;
- 使用时先通过宏RUNTIME_CLASS得到类的RunTime信息,然后使用CRuntimeClass的成员函数CreateObject创建一个该类的实例。
例如:
CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CNname)
//CName 必须有一个缺省构造函数
CObject* pObject = pRuntimeClass->CreateObject();
// 用IsKindOf检测是否是CName类的实例
Assert( pObject->IsKindOf(RUNTIME_CLASS(CName));
- 对序列化的支持
“序列化”就是把对象内容存入一个文件或从一个文件中读取对象内容的过程。从 CObject派生的类要具有序列化的功能,需要:
- 定义该类时,在类说明中使用DECLARE_SERIAL(CLASSNMAE)宏;
- 定义一个不带参数的构造函数(默认构造函数);
- 在类的实现文件中使用IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)宏;
- 覆盖Serialize成员函数。(如果直接调用Serialize函数进行序列化读写,可以省略前面三步。)
对运行时类信息的支持、动态创建的支持、串行化的支持层(不包括直接调用Serailize实现序列化),这三种功能的层次依次升高。如果对后面的功能支持,必定对前面的功能支持。支持动态创建的话,必定支持运行时类信息;支持序列化,必定支持前面的两个功能,因为它们的声明和实现都是后者包含前者。
- 综合示例:
定义一个支持串行化的类CPerson:
class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
// 缺省构造函数
CPerson(){}{};
CString m_name;
WORD m_number;
void Serialize( CArchive& archive );
// rest of class declaration
} ;
实现该类的成员函数 Serialize,覆盖CObject的该函数:
void CPerson::Serialize( CArchive& archive )
{
// 先调用基类函数的实现
CObject::Serialize( archive );
// now do the stuff for our specific class
if( archive.IsStoring() )
archive << m_name << m_number;
else
archive >> m_name >> m_number;
}
使用运行时类信息:
CPerson a;
ASSERT( a.IsKindOf( RUNTIME_CLASS( CPerson ) ) );
ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );
动态创建:
CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CPerson)
//Cperson 有一个缺省构造函数
CObject* pObject = pRuntimeClass->CreateObject();
Assert( pObject->IsKindOf(RUNTIME_CLASS(CPerson));
标签:MFC,const,函数,CRuntimeClass,void,深入浅出,CObject,构造函数 来源: https://blog.51cto.com/u_11041969/2908913
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。