RTTI(Runtime Type Identification/Information)
如果要实现运行时的RTTI,必须在类中加入一些唯一识别信息,静态成员变量则提供了这样一种方法。对于类而言,静态成员的地址信息是唯一确定的,这样就可以设计一种实现RTTI的方法。
1. typeid and dynamic_cast
标准C++中定义了type_info这个类用来表示对象的类型信息,同时增加了typeid运算符来取得类型信息。typeid()以一个对象或者类型名作为参数,返回一个匹配的const type_info对象来表明对象的确切类型。type_info常用的3个成员函数为operator ==()、operator !=()和name(),请参考标准头文件<typeinfo>。
对于“Class obj;”而言,typeid(obj)返回一个type_info对象的引用,而typeid(Class)返回一个type_info对象。
在多态类型(即带virtual函数的类)中,typeid()可以实现类似virtual函数动态绑定的功能,此时可以将typeid()看作是一个virtual函数。
除多态类型外,typeid()同样可以用来获得非多态类型对象和基本数据类型对象的类型信息。
注:typeid只能取得类型信息,而无法检查类间的继承关系,虽然它有类似虚函数动态绑定的功能。typeid的功能和下面讲述的RUNTIME_CLASS宏、GetRuntimeClass()函数在原理上类似。
如果要判断类之间的继承关系,则需要用到dynamic_cast<>这个算符。dynamic_cast实现类似下面提到的IsDerivedFrom()这个函数的功能。
2. RTTI in MFC
MFC中的RTTI实现方法和标准C++中应该是类似的,但MFC比C++标准中引入RTTI的时间要早,所以MFC提供了自己的一套方式。这里有一个模拟,比MFC中提供的要简单一些。(暂不提供一步步的设计过程,以后再加。)
补充:CRuntimeClass只是用来表示类型信息,而不是运行时类型信息(RTTI),将类继承关系中的各个CRuntimeClass对象组织起来,并使用IsDerivedFrom函数来判断继承关系,才是实现RTTI的核心所在。
#define RUNTIME_CLASS(class_name) /
(CRuntimeClass*)(&class_name::rtc##class_name)
#define DECLARE_DYNAMIC(class_name) /
public: /
virtual CRuntimeClass* GetRuntimeClass() const; /
static const CRuntimeClass rtc##class_name;
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) /
const CRuntimeClass class_name::rtc##class_name = {RUNTIME_CLASS(base_class_name)}; /
CRuntimeClass* class_name::GetRuntimeClass() const /
{ /
return RUNTIME_CLASS(class_name); /
}
struct CRuntimeClass
{
CRuntimeClass *m_pBase;
bool IsDerivedFrom(const CRuntimeClass *pBaseClass) const;
};
bool CRuntimeClass::IsDerivedFrom(const CRuntimeClass *pBaseClass) const
{
if (pBaseClass == NULL)
return false;
CRuntimeClass *pClass = (CRuntimeClass*)this;
while (pClass != NULL)
{
if (pClass == pBaseClass)
return true;
pClass = pClass->m_pBase;
}
return false;
}
class CObject
{
DECLARE_DYNAMIC(CObject)
public:
virtual ~CObject() {}
bool IsKindOf(const CRuntimeClass *pClass) const;
};
const CRuntimeClass CObject::rtcCObject = {NULL};
CRuntimeClass* CObject::GetRuntimeClass() const
{
return RUNTIME_CLASS(CObject);
}
bool CObject::IsKindOf(const CRuntimeClass *pClass) const
{
CRuntimeClass *pClassThis = GetRuntimeClass();
return pClassThis->IsDerivedFrom(pClass);
}
class CVehicle: public CObject
{
DECLARE_DYNAMIC(CVehicle)
public:
virtual ~CVehicle() {}
};
IMPLEMENT_DYNAMIC(CVehicle, CObject)
class CAnimal: public CObject
{
DECLARE_DYNAMIC(CAnimal)
public:
virtual ~CAnimal() {}
};
IMPLEMENT_DYNAMIC(CAnimal, CObject)
void Identify1(CObject *pObj)
{
if (pObj->GetRuntimeClass() == RUNTIME_CLASS(CVehicle))
{
cout << "This is a CVehicle object !" << endl;
return;
}
if (pObj->GetRuntimeClass() == RUNTIME_CLASS(CAnimal))
{
cout << "This is a CAnimal object !" << endl;
return;
}
cout << "Unknown object !" << endl;
}
void Identify2(CObject *pObj)
{
if (pObj->IsKindOf(RUNTIME_CLASS(CVehicle)))
{
cout << "This is a CVehicle derived object !" << endl;
return;
}
if (pObj->IsKindOf(RUNTIME_CLASS(CAnimal)))
{
cout << "This is a CAnimal derived object !" << endl;
return;
}
cout << "Unknown object !" << endl;
}
int main(void)
{
CVehicle vehicle;
CAnimal animal;
Identify1(&vehicle);
Identify1(&animal);
Identify2(&vehicle);
Identify2(&animal);
return 0;
}
两种实现方式的对比:
|
标准C++ |
MFC |
类型信息结构 |
type_info |
CRuntimeClass |
取得类型信息 |
typeid() |
RUNTIME_CLASS() GetRuntimeClass() |
判断继承关系 |
dynamic_cast<> |
IsDerivedFrom() |
原文链接: https://www.cnblogs.com/zhtwe/archive/2010/12/20/2159002.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/19013
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!