/* *
* 按照书中所说, 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;
}