一般来说我们尽量使用虚函数来进行动态类型绑定,但是我们想使用基类对象的指针或引用执行某个派生类操作并且该类不是虚函数时,我们要动态区分类对象的类型。
以下是接管类型管理的方法,实现动态类型识别的方法有三种:
在基类中定义虚函数,返回具体的类型信息
所有的派生类都必须实现类型相关的虚函数
每个类的虚函数都必须有不同的实现以进行类型区别
缺点:
必须从基类开始提供类型虚函数
所有的派生类都必须重写类型虚函数
每个派生类的类型ID必须唯一
不用显示的声明和定义类型虚函数
不用为类族中的每个类分配类型ID
缺点:
只能用于具有虚函数的类族
typeid返回一个type_info类对象
当typeid的参数为NULL时,抛出bad_typeid异常
type_info类的使用需要包含<typeinfo>
dynamic_cast关键字是可用于动态类型识别
typeid关键字在C++中专用于动态类型的识别
以下是接管类型管理的方法,实现动态类型识别的方法有三种:
c++的多态机制+标识类型的ID
实现方式:在基类中定义虚函数,返回具体的类型信息
所有的派生类都必须实现类型相关的虚函数
每个类的虚函数都必须有不同的实现以进行类型区别
缺点:
必须从基类开始提供类型虚函数
所有的派生类都必须重写类型虚函数
每个派生类的类型ID必须唯一
c++的dynamic_cast实现
优点:不用显示的声明和定义类型虚函数
不用为类族中的每个类分配类型ID
缺点:
只能用于具有虚函数的类族
c++的typeid实现
typeid关键字返回对应参数的类型信息typeid返回一个type_info类对象
当typeid的参数为NULL时,抛出bad_typeid异常
type_info类的使用需要包含<typeinfo>
总结:
C++中可以通过多态的方式进行动态类型识别dynamic_cast关键字是可用于动态类型识别
typeid关键字在C++中专用于动态类型的识别
最后以c++ primer一句话结束:使用RTTI必须加倍小心。在可能的情况下,最好定义虚函数而非直接接管类型管理的重任。
代码
#include <iostream>
#include <typeinfo>
using namespace std;
// way 1 多态机制
class Parent
{
public:
virtual int type()
{
return ID;
}
enum { ID = 0 };
};
class Child :public Parent
{
public:
int type()
{
return ID;
}
enum {ID = 1};
};
// 利用虚函数进行动态类型识别的方法可以满足工程的需要
// 但是维护性会随着派生类的增多而成指数级增加。
void test_polymorphism(Parent* p)
{
if (p->type() == Child::ID)
{
Child* c = (Child*)p;
cout << "The child class: " << c->type() << endl;
}
else
{
Parent*q = p;
cout << "The parent class: " << p->type() << endl;
}
}
// way 2 dynamic_cast,dynamic_cast实现父类指针向派生类的安全转换
class ParentDynamic
{
public:
virtual ~ParentDynamic()
{
}
};
class ChildDynamic :public ParentDynamic
{
public:
int add(int left, int right)
{
return left + right;
}
};
void test_dynamic(ParentDynamic* pd)
{
if (ChildDynamic* cd = dynamic_cast<ChildDynamic*>(pd))
{
cout << "The child_dynamic: " << cd->add(2, 3) << endl;
}
else
{
cout << "The parent_dynamic result." << endl;
}
}
// way 3 typeid typeid返回类型信息
class NewChildDynamic :public ParentDynamic
{
public:
};
void test_typeid(ParentDynamic* p)
{
if (typeid(*p) == typeid(ChildDynamic))
{
cout << "The ChildDynamic result." << endl;
}
else if (typeid(*p) == typeid(NewChildDynamic))
{
cout << "The NewChildDynamic result." << endl;
}
else
{
cout << "The ParentDynamic result." << endl;
}
}
int main()
{
Parent parent;
Child child;
int i;
char ch;
test_polymorphism(&parent);
test_polymorphism(&child);
ParentDynamic pd;
ChildDynamic cd;
test_dynamic(&pd);
test_dynamic(&cd);
NewChildDynamic ncd;
test_typeid(&pd);
test_typeid(&cd);
test_typeid(&ncd);
const type_info& tpa = typeid(parent);
const type_info& tch = typeid(child);
const type_info& tpd = typeid(pd);
const type_info& tcd = typeid(cd);
const type_info& tncd = typeid(ncd);
cout << tpa.name() << endl;
cout << tch.name() << endl;
cout << tpd.name() << endl;
cout << tcd.name() << endl;
cout << tncd.name() << endl;
}