【深入理解C++】RTTI、dynamic_cast、typeid()
创始人
2024-01-28 02:16:42
0

文章目录

  • 1.RTTI
  • 2.dynamic_cast运算符
  • 3.typeid运算符
  • 4.RTTI与虚函数表

1.RTTI

RTTI(Run Time Type Identification),即运行时类型识别,通过 RTTI,程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。

RTTI 提供了两个非常有用的运算符:

  • dynamic_cast 运算符:将基类类型的指针或引用安全地转换为其派生类类型的指针或引用。

  • typeid 运算符:返回指针或引用所指对象的实际类型。

要想让 RTTI 的两个运算符能够正常工作,那么基类中必须至少要有一个虚函数,不然这两个运算符工作的结果可能跟预期结果不一样,因为只有虚函数的存在,这两个运算符才会使用指针或引用所绑定的对象的动态类型。

2.dynamic_cast运算符

如果 dynamic_cast 运算符能够转换成功,说明这个指针实际上就是要转换到的那个类型,也就是说 dynamic_cast 运算符能够做运行时安全检查。

#include 
using namespace std;class Animal
{
public:virtual void run() { cout << "Animal::run()" << endl; }
};class Dog : public Animal
{
public:void run() { cout << "Dog::run()" << endl; }void speak() { cout << "Dog::speak()" << endl; }
};int main()
{Animal* pa = new Dog();//pa->speak(); // 报错Dog* pd = dynamic_cast(pa);if (pd != nullptr){cout << "转换成功" << endl;pd->speak(); // 正确}else{cout << "转换失败" << endl;}return 0;
}

对于引用,如果用 dynamic_cast 转换失败,则系统会抛出一个 std::bad_cast 异常,如下代码所示。

#include 
using namespace std;class Animal
{
public:virtual void run() { cout << "Animal::run()" << endl; }
};class Dog : public Animal
{
public:void run() { cout << "Dog::run()" << endl; }void speak() { cout << "Dog::speak()" << endl; }
};int main()
{Animal* pa = new Dog();Animal& refa = *pa;//refa.speak(); // 报错try{Dog& refd = dynamic_cast(refa); // 如果转换不成功,则流程直接进入到catch里边去;如果转换成功,则流程继续往下走cout << "转换成功" << endl;refd.speak(); // 正确}catch (std::bad_cast){cout << "转换失败" << endl;}return 0;
}

3.typeid运算符

typeid() 的主要作用就是让用户知道当前的变量是什么类型的。

typeid() 返回的是一个 type_info 类型的常量对象的引用,即 const type_info&。type_info 类中的成员函数 name() 返回的是一个C语言风格的字符串。

#include 
using namespace std;int main()
{int a = 180;cout << typeid(a).name() << endl;char b[] = "hello";cout << typeid(b).name() << endl;cout << typeid(19.6).name() << endl;cout << typeid("world").name() << endl;return 0;
}

输出结果如下:

在这里插入图片描述

#include 
using namespace std;class Animal
{
public:virtual void run() { cout << "Animal::run()" << endl; }
};class Dog : public Animal
{
public:void run() { cout << "Dog::run()" << endl; }
};class Cat : public Animal
{
public:void run() { cout << "Cat::run()" << endl; }
};int main()
{Animal* p1 = new Dog();cout << typeid(p1).name() << endl;cout << typeid(*p1).name() << endl;if (typeid(*p1) == typeid(Dog)){cout << "将Dog类型的对象动态绑定到p1指针上" << endl;}else{cout << "没有将Dog类型的对象动态绑定到p1指针上" << endl;}Animal* p2 = new Cat();cout << typeid(p2).name() << endl;cout << typeid(*p2).name() << endl;if (typeid(*p2) == typeid(Cat)){cout << "将Cat类型的对象动态绑定到p2指针上" << endl;}else{cout << "没有将Cat类型的对象动态绑定到p2指针上" << endl;}return 0;
}

输出结果如下:

在这里插入图片描述

如下代码所示,如果基类中不含有虚函数,则 typeid() 返回的是表达式的静态类型(即定义的类型),既然是定义的类型,那么编译器不需要对表达式求值也能知道表达式的静态类型。

#include 
using namespace std;class Animal
{
public:void run() { cout << "Animal::run()" << endl; }
};class Dog : public Animal
{
public:void run() { cout << "Dog::run()" << endl; }
};class Cat : public Animal
{
public:void run() { cout << "Cat::run()" << endl; }
};int main()
{Animal* p1 = new Dog();cout << typeid(p1).name() << endl;cout << typeid(*p1).name() << endl;if (typeid(*p1) == typeid(Dog)){cout << "将Dog类型的对象动态绑定到p1指针上" << endl;}else{cout << "没有将Dog类型的对象动态绑定到p1指针上" << endl;}Animal* p2 = new Cat();cout << typeid(p2).name() << endl;cout << typeid(*p2).name() << endl;if (typeid(*p2) == typeid(Cat)){cout << "将Cat类型的对象动态绑定到p2指针上" << endl;}else{cout << "没有将Cat类型的对象动态绑定到p2指针上" << endl;}return 0;
}

输出结果如下:

在这里插入图片描述

4.RTTI与虚函数表

#include 
using namespace std;class Animal
{
public:virtual void run() { cout << "Animal::run()" << endl; }
};class Dog : public Animal
{
public:void run() { cout << "Dog::run()" << endl; }
};int main()
{Animal* pa = new Dog();const type_info& tf = typeid(*pa);cout << tf.name() << endl; // class Dogreturn 0;
}

在 C++ 中,如果类中含有虚函数,那么编译器就会对该类产生一个虚函数表。

在上面代码中,pa 指向一个 Dog 类型的对象,该对象里有一个指针,称为虚函数表指针,虚函数表指针指向的是该对象所在的类 Dog 的虚函数表。

虚函数表里有很多项,每一项都是一个指针,每个指针指向的是这个类中的各个虚函数的入口地址。

虚函数表中的第一个表项很特殊,它指向的不是虚函数的入口地址,它指向的实际上是这个类所关联的 type_info 对象。

相关内容

热门资讯

新型中小投资项目 5个项目 新... 提起适合穷人的18个创业项目小投资的都有哪些,想必大家都有一定了解,有人问请问现在新型投资项目有哪些...
学生自主创业 学生自主创业 学... 以下是西安领军教育集团董事长吕鹏程在2012腾讯大秦网教育论坛主题演讲:学生自主创业不能说的秘密实录...
一个合适的创业合作伙伴很重要 ... 找到一个合适的创业合作伙伴那样的话,成功率就会大很多,可是要如何才能找到一个好的合作伙伴呢?下面由小...
学生自主创业项目 学生自主创业...   :保健面包房开一家面包店投资不大,对很多人来说是件容易的事。但用传统的烤制方式再加上传统的配料,...
深圳创业项目 深圳创业项目 深... 深圳市一个人杰地灵的地方,南方城市的标杆,很多年轻人都向往的城市,有挑战,更有机会,从数据上看深圳的...
农林致富好项目有哪些 这四个农... 农林致富好项目有哪些?现在大家都有一个思想,尤其是在农村不少人都想自己创业赚钱,因为毕竟在农村创业优...
代理小本创业新开店项目 代理小...   创业开店项目小本创业项目推荐:纺吧,休闲娱乐的新时尚1在城市繁华居民区里或在游乐休闲集聚地租一套...
浙江福建等地积极应对台风“丹娜...   央视网消息(新闻联播):7月7日,中央气象台发布台风蓝色预警。浙江、福建等地加强防范,积极应对将...
怎么创业 怎么创业 怎么创业呢... 一无所有的人怎么创业?分类:创业故事|如何创业|Word文档下载一无所有的人怎么创业?创业,先从认识...
你们是怎么创业的? 你们是怎么... 女朋友在毕业后的第1年内因为忍受不了事业单位的不良风气决定离职。同年,我因为忍受不了所任职私企的不良...