—————————————————————————————dynamic_cast———————————————————————————
http://jetyi.blog.51cto.com/1460128/671256
C++程序员大多喜欢使用强制类型转换(我也是),尽管它是C遗留下来的,尽管它存在这样那样的缺点,但是你不能不承认它使用起来很方便,而且绝大多数情况下是不会产生问题的.极少数情况下可能会存在类型转换失败的情况,这时候就需要使用到dynamic_cast了,这里提到的"极少数情况"是这样的:如果有继承或多重继承的类对象,你在某些情况下得到某个对象的指针,而你又想将其转换为某个特定类型,但是由于C++中对象类型的多态性(它可以是多种类型),你又不能确定(在运行时)这么做一定会成功,此时可以使用dynamic_cast,充分利用C++的运行时检查机制.只是用语言描述太抽象了,举个例子吧.
class A{...};
class B:public A{...};
class C:public B{...};
void Fun1(B* pB)
{
A* pA = (A*)pB;
C* pC = (C*)pB;
...
}
Fun1函数使用强制类型转换将pB转换为A*或C*,看出什么的问题了吗?
这时dynamic_cast就能大显身手了.
A* pA = dynamic_cast<A*>pB;// upcast.
if (NULL == pA){...}
C* pC = dynamic_cast<C*>pB;// downcast.
if (NULL == pC){...}
指针转换: dynamic_cast<ObjectType-ID*>(ObjectType*);
如果要成功地将ObjectType* 转换为ObjectType-ID*, 则必须存在这种可能性才可以,也就是说ObjectType*指向的对象 要"包含"ObjectType-ID*指向的对象,如此才能够成功, 否则返回NULL指针。
如果: A* pA = new B;
那么: B* pB = dynamic_cast<B*>pA; //OK.
C* pC = dynamic_cast<C*>pA; //Fail.
如果说你不能确定这种包含关系,最好使用dynamic_cast,然后对转换后的指针作NULL判断。
引用转换: dynamic_cast<ObjectType-ID&>(ObjectType&);
只有当ObjectType所引用的对象是OjbectType-ID&所引用的对象的派生类对象时才会转化成功。否则,抛出一个std::bad_cast异常
——————————————————————————————typeid—————————————————————————
typeid(表达式或类型名),返回类型的id
typeid操作符可以与任何类型的表达式一起使用。内置类型的表达式以及常量都可以作为typeid操作符的操作数。
(1)操作数不是类类型或者是没有虚函数的类,则typeid指出的是静态类型
(2)操作数是含虚函数的类类型,则typeid指出的是运行时计算类型
typeid最常见的用途是比较两个表达式的类型是否相同。
Base *bp;
Derived *dp;
if(typeid(*bp)==typeid(*dp)) // bp所指的对象类型是否和dp所指的相同
{
}
if(typeid(*bp)==typeid(Derived)) //bp所指的对象类型是否是Derived类型
{
}
if(typeid(bp)==typeid(Derived)) //typeid(bp)是Base*指针类型,而typeid(Derived)是对象类型,不相等
{
}
——————————————————————————————RTTI——————————————————————————
Runtime Type Information 运行时类型信息,动态判别执行时期的类型。通过RTTI,程序能够使用基类的指针或引用来检索这些指针或引用所指对象的实际派生类型。通过以下两个操作符提供RTTI:
(1)typeid操作符,返回指针或引用所指对象的实际类型
(2)dynamic_cast操作符,将基类类型的指针或引用安全地转化为派生类型的指针或引用
注:这两个操作符只为带有虚函数的类返回动态类型信息,对于其他类型,返回静态(即编译时)类型的信息
dynamic_cast 用于在类层次结构中漫游,对指针或引用进行自由的向上、向下或交叉转化。
typeid 用于获取一个对象或引用的确切类型。
一般来讲,能用虚函数解决的问题就不要用dynamic_cast,能够用dynamic_cast解决的就不要用typeid