关于dynamic_cast

http://www.groad.net/bbs/read.php?tid-5476.html

 

dynamic_cast 进行运行时强制转换。如果在执行时转换非法,则会转换失败。dynamic_cast 的通用形式如下:

dynamic_cast <target-type> (expr)


其中 target-type 指定了强制转换的目标类型,expr 是需要进行强制转换的表达式。

目标类型必须是指针类型或引用类型,也就是说,表达式也必须能够被求值为指针类型或者引用类型的结果。

dynamic_cast 主要被用来执行多态类型之间的强制转换。比如两个多态类 B 和 D,且 D 派生于 B,此时我们可以用 dynamic_cast 将 D* 指针类型转换为 B* 类型,这是因为基类型的指针通常可以指向派生类的对象。然而,只有当指针指向的对象确实是类 D 的对象时,dynamic_cast 才能将指针从类型 D* 转换为类型 B* 。

如果转换指针的类型失败时,经过 dynamic_cast 运算后得到的指针为空值。
如果转换引用的类型失败时,则会抛出 bad_cast 类型异常。

下面示例中,假设 Base 是多态类,Derived 派生于 Base ,那么:

?
1
2
3
4
5
6
Base *bp, b_ob;
Derived *dp, d_ob;
 
bp = &d_ob;           // 基类型的指针可以指向派生类的对象
 
dp = dynamic_cast <Derived *> (bp);   //强制转换基类指针为派生类指针,做法正确


上面,将基类指针 bp 强制转换为派生类指针 dp 是可以的,这是因为 bp 指向的对象确实是一个 Derived 类型的对象。

下面的是强制转换失败的示例:

?
1
2
bp = &b_ob;
dp = dynamic_cast <Derived *>(bp);     //错误


现在 bp 是一个指向基类对象的指针,这时不能 dynamic_cast 将其强制转换为派生类对象的指针,因为派生类对象的指针不能指向基类的对象。

下面是代码测试多种 dynamic_cast 的情况:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// dynamicast.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
using namespace std;
 
class Base {
public :
     virtual void f() { cout << "Inside Base.\n" ; }
};
 
class Derived : public Base {
public :
     void f() { cout << "Inside Derived\n" ; }
};
 
int _tmain( int argc, _TCHAR* argv[])
{
     Base *bp, b_ob;
     Derived *dp, d_ob;
 
     dp = dynamic_cast <Derived *>(&d_ob);     //派生类对象的指针强制转换为派生类对象的指针 OK
     if (dp) {
         cout << "Cast from Derived * to Derived * OK.\n" ;
         dp->f();
     } else
         cout << "Error\n" ;
     cout << endl;
 
     bp = dynamic_cast <Base *>(&d_ob);   //派生类对象的指针强制转换为基类的指针 OK(基类指针可以指向派生类的对象)
     if (bp) {
         cout << "Cast from Derived * to Base * OK.\n" ;    
         bp->f();
     } else
         cout << "Error\n" ;
     cout << endl;
 
     bp = dynamic_cast <Base *>(&b_ob);   //基类的指针强制转换为基类的指针 OK
     if (bp) {
         cout << "Cast from Base * to Base * OK.\n" ;
         bp->f();
     } else
         cout << "Error\n" ;
     cout << endl;
 
     dp = dynamic_cast <Derived *>(&b_ob);     //基类对象的指针(地址)强制转换为派生类的指针(失败)
     if (dp)
         cout << "Error\n" ;
     else
         cout << "Cast from Base * to Derived * not OK.\n" ;
     
     cout << endl;
 
     bp = &d_ob;         //bp 指向派生类的对象
     
     dp = dynamic_cast <Derived *> (bp);       //可以,因为 bp 确实已经指向了派生类
     if (dp) {
         cout << "Casting bp to Derived * OK\n" << "because bp is really pointing\n"
              << "to a Derived object.\n" ;
              dp->f();
     } else
         cout << "Error\n" ;
     cout << endl;
 
     bp = &b_ob;         //bp 指向基类型对象
     dp = dynamic_cast <Derived *> (bp);   //失败,因为 bp 现在已经确实指向了基类对象
     if (dp)
         cout << "Error" ;
     else {
         cout << "Now casting bp to a Derived *\n"
               << "is not OK because bp is really \n"
               << "pointing to a Base object.\n" ;
     }
     cout << endl;
 
     dp = &d_ob;         //dp 指向派生类对象
     bp = dynamic_cast <Base *> (dp);     //可以,基类指针可以指向派生类对象
     if (bp) {
         cout << "Casting dp to a Base * is OK.\n" ;
         bp->f();
     } else
         cout << "Error\n" ;
 
     return 0;
}


运行输出:

Cast from Derived * to Derived * OK.
Inside Derived

Cast from Derived * to Base * OK.
Inside Derived

Cast from Base * to Base * OK.
Inside Base.

Cast from Base * to Derived * not OK.

Casting bp to Derived * OK
because bp is really pointing
to a Derived object.
Inside Derived

Now casting bp to a Derived *
is not OK because bp is really
pointing to a Base object.

Casting dp to a Base * is OK.
Inside Derived

转载于:https://www.cnblogs.com/buxianghe/p/3257172.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值