[C++ PRIMER知识梳理] 19.2 运行时类型识别(RTTI)

/* *
 *	按照书中所说, C++的RTTI的功能由typeid和dynamic_cast两个运算符来实现.
 *
 *	1. dynamic_cast
 *
 *	主要用到的有两种形式
 *
 *	dynamic_cast<type *>(e) 用来转换指针
 *	dynamic_cast<type &>(e) 用来转换引用
 *
 *	其中e和type的关系必须满足如下三条之一才能成功返回:
 *
 *	1.1 e的类型是type的公有基类
 *	
 *	1.2 e的类型是type的公有派生类
 *
 *	1.3 e的类型和type的类型相同
 *
 *	对指针的转换失败时, 会返回0
 *
 *	对引用的转换失败时, 会抛出一个bad_cast异常
 *
 *	2. typeid
 *
 *	typeid(e)
 *
 *	其中e是一个任意的表达式, typedid会返回一个type_info类型
 *
 *	e是非类类型或者不包含虚函数的类时, typeid会返回该表达式的静态类型,
 *	否则, 当该对象是一个定义了虚函数的类的左值时, typeid直到运行时才能
 *	得到结果
 *
 * */

#include "cstdio"
#include "typeinfo"

class Base
{
public:
	virtual ~Base()
	{
	}
};

class Derived : public Base
{
public:
	~Derived()
	{
	}
};

void CastBase(Base *bp)
{
/* *
 *	    书中引入的一个trick, 将定义放在if语句中, 此时dp的作用域只在if中.
 * */
	if(Derived *dp = dynamic_cast<Derived *>(bp))
	{
		printf("cast success\n");
	}
	else
	{
		printf("cast failed\n");
	}
}

class Other
{
	
};

void CastNULL(Derived *dp)
{
	printf("cast dp\n");
}

void CastNULL(Base *bp)
{
	printf("cast bp\n");
}

void CastRefB2D(Base &base)
{
	try
	{
		dynamic_cast<Derived &>(base);
	} 
	catch (std::bad_cast)
	{
		printf("cast failed\n");
	}
}

void CastRefD2B(Derived &derived)
{
	try
	{
		dynamic_cast<Base &>(derived);
	}
	catch(std::bad_cast)
	{
		printf("cast failed\n");
	}
}

int main() 
{
/* *
 *	用例1: cast success
 * */
	printf("TestCase 1:\n");
	CastBase(new Derived());
/* *
 *	用例2: cast failed
 * */
	printf("TestCase 2:\n");
	CastBase(new Base());
/* *
 *	用例3: 1 
 * */
	printf("TestCase 3:\n");
	printf("%d\n", dynamic_cast<Derived *>(new Base()) == NULL);
/* *
 * 	结合用例1和3, 可以得出结论, dynamic_cast并不能将Base转化成Derived, 1.1中成功的情况所
 *	指的是将一个指向派生类对象的基类指针转化成派生类指针.
 * */
	
/* *
 *	书上说即使指针e所指对象为空, 转换也能成功进行, 只不过返回值仍是空指针, 但是是
 *	type类型的空指针.
 * */
	Base *bp = NULL, *dp = NULL;
	printf("TestCase 4:\n");
	CastNULL(dynamic_cast<Derived *>(bp));
	printf("TestCase 5:\n");
	CastNULL(dynamic_cast<Base *>(dp));
/* *
 *	引用类型的转换书中只给了一个很简单的例子. 可以看到, 派生类向基类转换是会失败的
 * */
	Base base;
	printf("TestCase 5:\n");
	CastRefB2D(base);
	
	Derived derived;
	printf("TestCase 6:\n");
	CastRefD2B(derived);



/* *
 *	用例7: 	dp == bp (1)
 * */
	dp = new Derived();
	bp = dp;
	
	printf("TestCase 7:\n");
	printf("dp == bp (%d)\n", typeid(*bp) == typeid(*dp));

/* *
 *	用例8: bp is Derived (1)
 * */
	
	printf("TestCase 8:\n");
	printf("bp is Derived (%d)\n", typeid(*bp) == typeid(Derived));

/* *
 *	上述两个用例说明, 对有虚函数的类的左值进行求值返回的类型是其动态类型
 * */


	Other *other = NULL;
/* *
 *	用例9: 
 * */	
	printf("TestCase 9:\n");
	try
	{
		typeid(*other);
	}
	catch(std::bad_typeid)
	{
		printf("other failed\n");
	}

	bp = NULL;
/* *
 *	用例10: bp failed
 * */	
	printf("TestCase 10:\n");
	try
	{
		typeid(*bp);
	}
	catch(std::bad_typeid)
	{
		printf("bp failed\n");
	}
/* *
 *	上述两个用例说明, 静态类型求类型, 表达式不会被计算, 
 *	而动态类型则会被计算
 * */

/* *
 *	用例11: 5Other
 * */

	printf("TestCase 11:\n");
	printf("%s\n", typeid(*other).name());

/* *
 *	用例11主要是想说明, type_info有name()方法来获取类名
 * */

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值