|
|
Ashes to ashes Dust to dust
|
| |
|
|
| |
|
|
|
[VC++学习]《精通MFC》——第四章(III) 读书笔记
|
|
对于对象型的成员,则可以使用ASSERT_VALID宏测试它们内部有效性(如果它们的类重写了AssertValid)。
2.1 运行时类错误
CRuntimeClass结构
CRuntimeClass提供了对C++对象的运行时的类信息,下面是其声明:
演示代码: P106
CRuntimeClass结构还维持指向基类的CRuntimeClass指针,这样,按照类的派生关系构成了CRuntimeClass链表。通过查找该链表中是否有指定的CRuntimeClass,可判断给定的类是否从某个类派生:
演示代码: P108
通过m_pNextClass静态成员,MFC为每个模块(规则DLL或者EXE应用程序)维护一个全局的CRuntimeClass链表,该链表保存在模块状态中。当实例化CRuntimeClass的m_pClassInit时,将调用AfxClassInit把CRuntimeClass放到全局的CRuntimeClass链表中去。
void AFXAPI AfxClassInit(CRuntimeClass* pNewClass)
{
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
pModuleState->m_classList.AddHead(pNewClass);
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
}
添加运行时类信息
为了添加运行时类的信息,需要为类添加CRuntimeClass类型的静态成员,保存本类的相关信息。
凡是从CObject类派生的类,都可以通过一组宏自动完成上述任务。
首先在类的头文件中加入DECLARE_DYNAMIC宏。
class CPerson:public CObject
{
DECLARE_DYNAMIC(CPerson)
//其它声明
};
DECLARE_DYNAMIC宏声明了CRuntimeClass类型的静态成员,其名字为“classclass_name”(例如如果传入的class_name参数为CPerson,则对应的变量名为classCPerson)和一个返回CRuntimeClass指针的虚函数:
#define DECLARE_DYNAMIC(class_name)
public:
static const CRuntimeClass class##class_name;
virtual CRuntimeClass* GetRuntimeClass()const;
接下来在类的实现文件(.CPP)中使用IMPLEMENT_DYNAMIC宏。该宏包含两个参数:当前类和基类的类名。
IMPLEMENT_DYNAMIC(Cperson, CObject)
总是将IMPLEMENT_DYNAMIC放入类的实现文件(.CPP)中。编译期间,仅应计算一次IMPLEMENT_DYNAMIC宏,因此,该宏不能在潜在包含在不止一次的头文件中出现。
IMPLEMENT_DYNAMIC宏初始化上一步中声明的CRuntimeClass类型的静态成员,要设定类名、对象大小、基类的CRuntimeClass,将wSchema设置为0xFFF,表示不支持序列化,将m_pfnCreateObject设置为NULL,表示不支持动态创建,将class_init也设置为NULL。
IMPLEMENT_DYNAMIC宏还提供GetRuntimeClass()const
{return RUNTIME_CLASS(class_name);}
其中,宏RUNTIME_CLASS(className)返回类className的CRuntimeClass类型的静态成员的指针:
#define RUNTIME_CLASS(class_name)((CRuntimeClass*)(&class_name::class##class_name))
IsKindOf
CObject成员函数IsKindOf利用CRuntimeClass静态成员确定具体某个对象是属于特定类还是从特定类派生。
BOOL IsKindOf(const CRuntimeClass* pClass)const;
参数pClass表示要比较的类,如果当前对象是pClass或pClass的派生类,则返回TRUE,否则返回FALSE。CObject::IsKindOf内部调用了CRuntimeClass::IsDerivedFrom:
bool CObject::IsKindOf(const CRuntimeClass* pClass)const
{
CRuntimeClass* pClassThis = GetRuntimeClass();
return pClassThis->IsDerivedFrom(pClass);
}
如果类支持运行时信息,那么使用带类名的RUNTIME_CLASS宏可以获取表示该类信息的CRuntimeClass对象。例如:
CRuntimeClass* pClass = RUNTIME_CLASS(CPerson);
或者,通过对象调用GetRuntimeClass成员,也可以获得该对象所属类的类信息成员。
一旦获得运行时类对象,将其传递到IsKindOf函数。
void SomeFunction(void)
{
CObject* pMyObject = new CPerson;
if (pMyObject->IsKindOf(RUNTIME_CLASS(CPerson)))
{
CPerson* pmyPerson = (CPerson*)pMyObject;
...
delete pmyPerson;
}
...
delete pMyObject;
}
2.2 动态创建
遵循下面的步骤为类添加动态创建的功能。
从CObject派生类。然后再类声明中使用DECLARE_DYNCREATE宏。该宏内 部使用DECLARE_DYNAMIC,宏外还声明了静态成员CreateObject以支持动态创 建:
#define DECLARE_DYNCREATE(class_name)
DECLARE_DYNAMIC(class_name)
static CObject* PASCAL CreateObject(); |
|
|
|
|
| |
| ♀链接 |
|
AoGo汇编小站: http://www.aogosoft.com/
CSDN: http://www.csdn.net/
编程爱好者: http://www.programfan.com/
阿蒙编程之家: http://www.vchome.net/
看雪学院: http://www.pediy.com
VC开发指南:http://www.copathway.com
|