[C++ primer]运行时类型识别(RTTI)

 

通过RTTI,程序能够通过基类的指针或引用来检索其所指对象的实际类型。c++通过下面两个操作符提供RTTI。

(1)typeid:返回指针或引用所指对象的实际类型。

(2)dynamic_cast:将基类类型的指针或引用安全的转换为派生类型的指针或引用。

对于带虚函数的类,在运行时执行RTTI操作符,返回动态类型信息;对于其他类型,在编译时执行RTTI,返回静态类型信息。

在某些情况下不可能使用虚函数,在这种情况下,RTTI提供了可选机制。然而,这种机制比使用虚函数更容易出错:程序员必须知道应该将对象强制转换为哪种类型,并且必须检查转换是否成功执行。

注:使用动态强制类型转化要小心。只要有可能,定义和使用虚函数比直接接管类型管理好得多。

1、dynamic_cast操作符

dynamic_cast操作符将基类类型的指针或者引用安全转化为派生类类型的指针和引用。

如果dynamic_cast转换指针类型失败,则返回0;如果转换引用类型失败,则抛出一个bad_cast类型的异常。

dynamic_cast会首先验证转换是否有效,只有转换有效,操作符才进行实际的转换。

#include <iostream>
#include <typeinfo.h>
using namespace std;

class Base//基类是多态类
{
public:
	virtual void f()
	{
		cout<<"Inside Base."<<endl;
	}
};
class Derived : public Base
{
public:
	void f()
	{
		cout<<"Inside Derived."<<endl;
	}
};

void main()  
{  
    cout<<"Start"<<endl; 
	
	Base *bp,b_ob;
	Derived *dp,d_ob;
	//-------------------------------------
	dp=dynamic_cast<Derived*>(&d_ob);//派生类对象的指针“强制转换为”派生类对象的指针 OK
	if(dp)
	{
		cout<<"Cast from Derived* to Derived* Ok."<<endl;
		dp->f();
	}
	else
		cout<<"Error!"<<endl;
	//--------------------------------------
	bp=dynamic_cast<Base*>(&d_ob);//派生类对象的指针“强制转换为”基类对象的指针 OK
	if(bp)
	{
		cout<<"Cast from Derived* to Base* OK."<<endl;
		bp->f();
	}
	else
		cout<<"Error!"<<endl;
	//---------------------------------
	bp=dynamic_cast<Base*>(&b_ob);//基类对象的指针“强制转换为”基类对象的指针 OK
	if(bp)
	{
		cout<<"Cast from Base* to Base* OK."<<endl;
		bp->f();
	}
	else
		cout<<"Error!"<<endl;
	//-------------------------------------
	bp=dynamic_cast<Derived*>(&b_ob);//基类对象的指针“强制转换为”派生类对象的指针 Error
	if(bp)
	{
		cout<<"Cast from Base* to Base* OK."<<endl;
		bp->f();
	}
	else
		cout<<"Cast from Base* to Base* not OK."<<endl;
	//=====================================================
	bp=&d_ob;
	dp=dynamic_cast<Derived*>(bp);//指向派生类的基类指针“强制转换为”派生类对象的指针 OK
	if(dp)
	{
		cout<<"casting bp to a Drived* OK."<<endl;
		cout<<"because bp is really pointing to a Derived object."<<endl;
		dp->f();
	}
	else 
		cout<<"Error!"<<endl;
	//-------------------------------------------------------
	bp=&b_ob;//bp指向基类型的对象
	dp=dynamic_cast<Derived*>(bp);//指向基类型对象的指针“强制转换为”派生类对象的指针 OK
	if(dp)
		cout<<"Error!"<<endl;
	else
	{
		cout<<"Now casting bp to a Drived* is not ok."<<endl;
		cout<<"because bp is really pointing to a Base object."<<endl;
	}
	//---------------------------------------------------------
	dp=&d_ob;//dp指向基类型的对象
	bp=dynamic_cast<Base*>(dp);//指向派生类型对象的指针“强制转换为”指向基类对象的指针 OK
	if(dp)
	{
		cout<<"Casting dp to a base* is ok"<<endl;
		bp->f();
	}
	else
		cout<<"Error"<<endl;
    cout<<"End"<<endl;  
}  

 

2、typeid操作符

typeid表达式形如:typeid(e)

这里e是任意表达式或者是类型名。

如果操作数不是类类型或者是没有虚函数的类,则获取其静态类型;如果操作数是定义了至少一个虚函数的类类型,则计算运行时类型。

typeid最常见的用途是比较两个表达式的类型,或者将表达式的类型与特定类型相比较。

Base *bp;
Derived *dp;
// compare type at run time of two objects
if (typeid(*bp) == typeid(*dp))
{
    // bp and dp point to objects of the same type
}
// test whether run time type is a specific type
if (typeid(*bp) == typeid(Derived))
{
    // bp actually points a Derived
}

引用文献:

http://blog.csdn.net/yjkwf/article/details/5514833

原文地址:https://www.cnblogs.com/kona/p/4658661.html