C++ RTTI,dynamic_cast,typeid,type_info类,虚函数表 看这一篇就够了

RITTI :运行时类型识别

通过运行时类型识别,程序能够使用基类的指针或者引用,来检查这些指针或者引用所值得对象的实际派生类型。
RTTI可以看做系统提供给我们的一种功能。通过两个运算符体现。

  1. dynamic_cast:能够将基类的指针或者引用安全的转换为派生类的指针或者引用。
  2. typeid运算符:返回指针或者引用所指向的实际类型。
  3. 补充:RTTI的两个运算符想要正常工作,基类中至少有一个虚函数。不然这两个运算符工作的结果和我们的预测不一致。只有虚函数的存在,这两个运算符才会使用指针或者引用所绑定的对象的动态类型。
  4. 父类虚函数,子类重写,父类指针调用该函数的时候,会执行子类的函数,如果不是虚函数,则不能调用。

dynamic_cast运算符

如果该运算符能够转换成功,说明这个指针实际上是要转换到的那个类型。dynamic_cast 会做安全检查。dynamic_cast:转换成子类或者基类类型。

	//指针类型
	Human* ph = new Man;//Human 里面必须有虚函数
	Man* p1 = (Man*)ph;//c语言强制类型转换。不安全

	Man* p2 = dynamic_cast<Man*> (ph);//注意括号
	if(p2 != NULL)//如果成功,p2会等于NULL
		p2->testfunc();
	else
	{
		//转换失败
	}

对于引用,如果dynamic_cast转换失败,系统会抛出一个bad_casty异常。try{}…catch(){}捕获。

	Human* ph = new Man;//Human 里面必须有虚函数	
	Human& q = *ph;
	try
	{
		Man men = dynamic_cast<Man&>(q);//转成功,执行
		men.testfunc();
	}
	catch (bad_cast)//转换失败进入
	{
		cout << "转换失败" << endl;
	}

typeid运算符

typeid(类型,指针,引用),typeid(表达式)
拿到对象的信息,返回一个 常量对象的引用,是一个标准库类型typeid_info(类,类型)。

	Human* ph = new Man;//Human 里面必须有虚函数	
	Human& q = *ph;
	cout << typeid(*ph).name()<<endl;//class Man
	cout << typeid(q).name() << endl;//class Man
	cout << typeid(12).name() << endl;
	cout << typeid(1.2).name() << endl;
	cout << typeid("123").name() << endl;
	cout << typeid(1+3.5).name() << endl;

常用用途:比较两个指针是否指向同一个类型。

	Human* ph = new Man;//Human 里面必须有虚函数	
	Human* ph2 = new Women;
	if (typeid(ph) == typeid(ph2))//直接用指针名比价,看定义类型,不符合我们要求
	{
		cout << "ph 和 ph2 是同一种类型" << endl;
	}

	//比较的时候,想比较的是new的是不是同一个类。
	if (typeid(*ph) != typeid(*ph2))//用指针指向的对象(*p),看new,一定不要忘记*
	{
		cout << "*ph 和 *ph2 不是同一种类型" << endl;
	}

	if (typeid(*ph) == typeid(Man))//可以直接typeid(类名)
	{
		cout << "ph指向Man" << endl;
	}

基类必须要有虚函数,否则条件不成立
只有基类中有虚函数时,编译器才会对typeid()中的表达式求值,如果基类中不含虚函数,则typeid()返回表达式的静态类型(定义时的类型)。编译器就无需对表达式求值。

type_info类

typeid会返回一个 常量对象的引用,这个常量对象时一个标准库类型,type_info(类,类型)。
常用函数:
1. .name()

	Human* ph = new Man;//Human 里面必须有虚函数	
	const type_info& tp = typeid(*ph);
	cout << tp.name() << endl;//class Man

2. ==, !=

	Human* ph = new Man;//Human 里面必须有虚函数	
	const type_info& tp = typeid(*ph);
	Human* ph2 = new Man;//Human 里面必须有虚函数
	const type_info& tp2 = typeid(*ph2);
	if (tp2 == tp)//相同,进入
	{
		cout << "类型形同" << endl;
	}

	Human* ph3 = new Women;//Human 里面必须有虚函数
	const type_info& tp3 = typeid(*ph3);
	if (tp3 == tp)//不相同,无法进入
	{
		cout << "类型形同" << endl;
	}

虚函数表

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

  1. 表里有很多项,每一项都是一个指针,每个指针指向的是这个类的各个虚函数的入口地址。
  2. 虚函数表项里,第一个表项很特殊,指向的不是虚函数的入口地址,他指向的是类所关联的tpye_info对象。
	Human* ph = new Man;//Human 里面必须有虚函数	
	const type_info& tp = typeid(*ph);
	//ph对象中有一个看不见的指针,这个指针指向这个对象所在的类(Man)里的虚函数表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值