作用
在程序运行过程中可以获知对象的类的相关信息(例如对象是否属于某个类)
使用条件
- 类派生自CObject
- 类内添加声明宏 DECLARE_DYNAMIC(theClass)
- 类外添加实现宏 IMPLEMENT_DYNAMIC(theClass, baseClass)
使用方式
类对象名.IsKindOf(RUNTIME_CLASS(想要判断是否在其中的类名))
使用代码示例
//掐头
class CMonster:public CObject
{
DECLARE_DYNAMIC(CMonster)
};
IMPLEMENT_DYNAMIC(CMonster, CObject)
int main()
{
CMonster Shrem;
if(shrem.IsKindOf(RUNTIME_CLASS(CMonster)))
{
std::cout << "Shrem is Monster" << std::endl;
}
else
{
std::cout << "Shrem is not Monster" << std::endl;
}
}
//去尾
你如果没有需求的话就不用往下看原理了,挺绕的
原理
把我们在上述代码中书写的宏展开后,其实就相当于在类内添加了public属性的一个静态变量(结构体)和一个虚函数
static const CRuntimeClass classCMonster;
virtual CRuntimeClass* GetRuntimeClass() const
静态变量和虚函数返回值都牵扯到CRunTimeClass结构体
CRunTimeClass详细介绍去MSDN查看,此处只介绍成员变量
运行时类信息机制能用到的CRunTimeClass结构体的成员变量就只有前三个
本类的CRunTimeClass结构体的第三成员指针指向父类的CRunTimeClass结构体,层层继承之下,每个类的CRunTimeClass成员的指针都指向父类结构体,于是就形成了一个链表,最子类的结构体就是链表头,CObject类(最基类)的CRunTimeClass成员就是链表尾,且其CRunTimeClass的第三成员指针为NULL。
virtual CRuntimeClass* GetRuntimeClass() const函数的作用
返回本函数所在类的CRunTimeClass静态变量的地址
RUNTIME_CLASS宏的作用
RUNTIME_CLASS代换内容如下:
//RUNTIME_CLASS(CMonster)
//↓↓↓↓↓↓↓↓
((CRuntimeClass*)(&CMonster::classCMonster))
可以看出,RUNTIME_CLASS的作用即得到参数传递的类对象的CRunTimeClass静态变量的地址
IsKindOf函数执行流程
IsKindOf函数定义:BOOL CObject::IsKindOf(const CRuntimeClass*pClass) const
1. 参数RUNTIME_CLASS(CObject)能够拿到CObject类的CRunTimeClass成员地址
2. 调用本类的GetRuntiomClass虚函数,将链表头地址保存到pClassThis中
3. 函数最后pClassThis -> IsDerivedFrom(pClass),调用IsDerivedFrom函数
4. 在IsDerivedFrom函数内部有一个循环,从链表头开始遍历链表寻找是不是有个节点的地址跟传参的地址一样,有的话返回true,没有返回false,继而IsKindOf也会根据IsDerivedFrom的返回值返回。