RTTI 运行时类型识别技术
RTTI(Run Time Type Identification)运行时类型识别技术
常用场景:使用父类指针或者引用来检查这些指针或者引用所指向的对象的实际派生类型。
常用运算符:
(1)dynamic_cast运算符:能将父类的指针或者引用安全地转换为子类的指针或者引用
(2)typeid运算符:返回指针或者引用所指向的对象的实际类型
dynamic_cast运算符
使用dynamic_cast将父类指针转换为子类对象,若父类指针所指向的是相应类型的子类对象,则转换成功,返回对应的对象指针,否则转换失败,返回nullptr
如果是引用类型,失败则会抛出std::bad_cast异常
// dynamic_cast运算符,指针类型示例代码
Animal* pAnimal = new Cat;
Cat* pCat = dynamic_cast<Cat *>(pAnimal);
if(pCat != nullpter)
{
// 在此处写相应代码
}
// dynamic_cast运算符,引用类型示例代码
Dog rLDog;
Animal &rLAnimal = rLDog;
try
{
Dog &rDog = dynamic_cast<Dog&>(rLAnimal )
}
catch(bad_cast)
{
}
注意:使用dynamic_cast运算符的前提条件是父类中必须至少有一个虚函数,否则使用dynamic_cast运算符将编译报错,在较老的版本中,虽然能够编译过,但是无法得到正确的结果
typeid运算符
通过运用typeid运算符,可以获得对象的类型信息。这个运算符会返回一个常量对象的应用。这个常量对象的类型是标准库类型type_info。下面我们首先介绍一下type_info类:
type_info类常用的成员函数:
(1)name,用于获取类型名字信息
(2)==:两个type_info表示同一类型时返回true,否则返回false
(3)!= : 两个type_info表示同一类型时返回false,否则返回true
(4)hash_code 将 typeinfo 类型的值映射到索引值的分布的哈希函数
(5)raw_name成员函数返回一个const char*表示对象类型的修饰名称的 null 终止字符串。 该名称实际上以其修饰的形式存储以节省空间。 因此,此函数的速度比 type_info::name 它不需要取消命名更快。 该函数返回 的字符串在比较操作中很有用,但不可读。 如果需要人可读字符串,请改用该 type_info::name 函数。必须包含typeinfo头文件才能使用type_info类
不能直接实例化 type_info 类的对象,因为该类只有专用复制构造函数。 构造 (临时 ) type_info 对象的唯一方法是使用 typeid 运算符。 由于赋值运算符也是私有的,因此不能复制或分配类 type_info的对象
// type_info类的接口定义
class type_info {
public:
type_info(const type_info& rhs) = delete; // cannot be copied
virtual ~type_info();
size_t hash_code() const;
_CRTIMP_PURE bool operator==(const type_info& rhs) const;
type_info& operator=(const type_info& rhs) = delete; // cannot be copied
_CRTIMP_PURE bool operator!=(const type_info& rhs) const;
_CRTIMP_PURE int before(const type_info& rhs) const;
size_t hash_code() const noexcept;
_CRTIMP_PURE const char* name() const;
_CRTIMP_PURE const char* raw_name() const;
};
好了,介绍完了type_info类,接下来该介绍typeid的使用了,这里还是直接上代码吧
Animal *pAnimal = new Dog;
const std::type_info& tp = typeid(*pAnimal);
cout << tp.name()<<endl; // Class Dog
注意:使用typeid运算符的前提条件是父类中也必须至少有一个虚函数