dynamic_cast转换符只能用于指针或者引用。dynamic_cast转换符只能用于含有虚函数的类。dynamic_cast转换操作符在执行类型转换时首先将检查能否成功转换,
如果能成功转换则转换之,如果转换失败,如果是指针则反回一个0值,如果是转换的是引用,则抛出一个bad_cast异常,所以在使用dynamic_cast转换之间应使用
if语句对其转换成功与否进行测试,比如
if(dynamic_cast<D*>(pb))
{
...
}
else
{
...
}
dynamic_cast能将基类类型的指针或引用安全地转换为派生类型的指针或引用, 它是怎么实现的呢?
它是通过运行时类型识别(RTTI),程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型,在第2部分会介绍。
reinterpret_cast< type > ( object )
type 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针
(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。
操作符修改了操作数类型,但仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换。
C++中static_cast和reinterpret_cast的区别:
C++primer里写了编译器隐式执行任何类型转换都可由static_cast显示完成;reinterpret_cast通常为操作数的位模式提供较低层的重新解释。
C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:
int i;
char *p = "This is a test.";
i = reinterpret_cast<int>(p);
此时结果,i与p的值是完全相同的。reinterpret_cast的作用是说将指针p的值以二进制(位模式)的方式被解释为整型,并赋给i.
二、RTTI
RTTI(Run-Time Type Information,通过运行时类型信息)程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
RTTI提供了以下两个非常有用的操作符:
(1)typeid操作符,返回指针和引用所指的实际类型。
(2)dynamic_cast操作符,将基类类型的指针或引用安全地转换为派生类型的指针或引用。
typeid 操作符的结果是名为type_info的标准库类型的对象引用,类type_info在库头文件 typeinfo中定义。typeid 操作符可以与任何类型的表达式一起使用。
内置类型的表达式以及常量都可以用作 typeid 操作符的操作数。如果操作数不是类类型或者是没有虚函数的类,则 typeid 操作符指出操作数的静态类型;
如果操作数是定义了至少一个虚函数的类类型,则在运行时计算类型。
Base *bp;
Derived *dp;
// compare type at run time of twoobjects
if (typeid(*bp) ==typeid(*dp)) {
// bp and dp point to objects of thesame type
}
// test whether run time type is aspecific type
if (typeid(*bp) ==typeid(Derived)) {
// bp actually points to aDerived
}//特别注意,只有当 typeid 的操作数是带虚函数的类类型的对象的时候,才返回动态类型信息.
type_info的复制构造函数以及赋值操作符都定义为 private,所以不能定义或复制 type_info类型的对象。程序中创建 type_info 对象的唯一方法是使用 typeid 操作符。
type_info类确切定义随编译器而变化,但是标准保证至少实现operator==,operator=!,type_info::name()及type_info::before()。
运行时获知变量类型名称,可以使用 typeid(变量).name ,如:printf("%s\n", typeid(int).name()); 其输出不一定是 int ,我这里输出是 i。
对dynamic_cast 它究竟是怎么实现的呢?
最简单的方案就是将信息保存在vtable里,它会占用一个vtalbe表的项目,具体做法可以参考大作《Inside C++ Model》RTTI 的info 是如何和对象之间的关联。
举例
class Point
{
public:
Point( float xval );
virtual ~Point();
float x() const;
static int PointCount();
protected:
virtual ostream& print( ostream &os ) const;
float _x;
static int _point_count;
};
其对应的内存模型: