C++ dynamic_cast的一点心得[转]

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://jetyi.blog.51cto.com/1460128/671256 # 缘由 # C++程序员大多喜欢使用强制类型转换(我也是),尽管它是C遗留下来的,尽管它存在这样那样的缺点,但是你不能不承认它使用起来很方便,而且绝大多数情 况下是不会产生问题的.极少数情况下可能会存在类型转换失败的情况,这时候就需要使用到dynamic_cast了,这里提到的“极少数情况”是这样的: 如果有继承或多重继承的类对象,你在某些情况下得到某个对象的指针,而你又想将其转换为某个特定类型,但是由于C++中对象类型的多态性(它可以是多种类 型),你又不能确定(在运行时)这么做一定会成功,此时可以使用dynamic_cast,充分利用C++的运行时检查机制.只是用语言描述太抽象了,举 个例子吧.

1
2
3
4
5
6
7
8
9
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*,看出什么的问题了吗?

如果这样调用Fun1:

1
Fun1(((B*)new C));

的确不会有问题,但如果是这样呢:

1
Fun1(new B);

pC不会为NULL,能够想到使用pC指针时就程序就悲剧了.

更严重情况下,如果是这样:

1
Fun1((B*)0X00005678);//0X00005678是一个随机值

pA,PC就不会是NULL,强制类型转换总是能够成功的,但使用这两个指针时程序肯定崩溃.当然你可以使用异常处理机制来处理这样的错误,不过这有点大才小用的感觉,最好能够找到一种能够检查出类型转换能否成功的办法.这时dynamic_cast就能大显身手了.

1
2
3
4
A* pA = dynamic_cast<A*>pB;// upcast.
if (NULL == pA){...}
C* pC = dynamic_cast<C*>pB;// downcast.
if (NULL == pC){...}

dynamic_cast的具体作用这里不详细解释,仅仅抛砖引玉做一点说明.这里假设:

1
dynamic_cast < ObjectType-ID* > ( ObjectType*)

如果要成功地将ObjectType*转换为ObjectType-ID*,则必须存在这种可能性才可以,也就是说ObjectType*指向的对象要“包含”ObjectType-ID*指向的对象,如此才能够成功.就上面的例子来说,C对象“包含”B对象,而B对象“包含”A对象,如果:

1
A* pA = new B;

那么

1
2
B* pB = dynamic_cast<B*>pA;// OK.
C* pC = dynamic_cast<C*>pA;// Fail.

如果说你不能确定这种包含关系,最好使用dynamic_cast.

实际上可以把dynamic_cast看做是强制类型转换的一个子集,看成是更严格检查的强制类型转换,因为“更严格”所以能够检查出来错误.

最后提一点,使用dynamic_cast,不要忘了编译选项GR.

练习

最后给大家出道题巩固下啊:

1
2
3
4
5
6
7
8
9
10
11
12
class A {};
class B :public A{};
class C :public B{};
class D :public B , public A{};
下面哪一项转换失败:
a. A * pa = new C;
B * pb = dynamic_cast<B*> pa;
b. B *pb = new B;
C *pc = dynamic_cast<C*> pb;
c. A *pa = new D;
B *pb = dynamic_cast<B*> pa;

我不会告诉你答案是B的~~~

热评文章