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

关于dynamic_cast的更多相关文章

  1. RTTI: dynamic_cast typeid

    dynamic_cast:将基类类型的指针向派生类指针安全转换.多用于下行转换.上行转换时,和static_cast是一样的.C++类型转换看这里.而const_cast用来修改类型的const或vo ...

  2. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  3. C++ dynamic_cast对指针类型的转换

    C8-3 三角形还是长方形? (100.0/100 points) 题目描述 在多态概念中,基类的指针既可以指向基类的对象,又可以指向派生类的对象.我们可以使用dynamic_cast类型转换操作符来 ...

  4. dynamic_cast 和 static_cast 隐式类型转换的区别

    首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...

  5. C++ 中dynamic_cast&lt;&gt;的使用方法小结 -判断类型-rtti

    将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理          即会作一定的判断.        对指针进行dynamic ...

  6. C++强制类型转换操作符 dynamic_cast

    dynamic_cast是四个强制类型转换操作符中最特殊的一个,它支持运行时识别指针或引用. >>>>>>>>>>>编译器的RTTI设 ...

  7. static_cast、dynamic_cast、reinterpret_cast、const_cast以及C强制类型转换的区别

    static_cast 1. 基础类型之间互转.如:float转成int.int转成unsigned int等 2. 指针与void*之间互转.如:float*转成void*.CBase*转成void ...

  8. c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

    c++强制类型转换:dynamic_cast.const_cast .static_cast.reinterpret_cast 博客分类: C/C++ CC++C#编程数据结构  dynamic_ca ...

  9. static_cast dynamic_cast const_cast reinterpret_cast总结对比

    [本文链接] http://www.cnblogs.com/hellogiser/p/static_cast-dynamic_cast-const_cast-reinterpret_cast.html ...

  10. static_cast, dynamic_cast, const_cast

    http://www.cnblogs.com/chio/archive/2007/07/18/822389.html 首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1 ...

随机推荐

  1. 《Linux shell编程中 diff与vimdif的使用》RHEL6

    linux比较2个文件的区别有两个命令: (1)diff (2)vimdiff cp /etc/grub.conf hello 在hello文件的末尾添加zhangsan 使用diff比较2个文件的区 ...

  2. 延迟加载图片的 jQuery 插件:Lazy Load

    网站的速度非常重要,现在有很多网站优化的工具,如 Google 的Page Speed,Yahoo 的 YSlow,对于网页图片,Yahoo 还提供 Smush.it这个工具对图片进行批量压缩,但是对 ...

  3. struct和class区别

    转载来源:http://blog.sina.com.cn/s/blog_48f587a80100k630.html C++中的struct对C中的struct进行了扩充,它已经不再只是一个包含不同数据 ...

  4. fastclick插件 导致 input[type="date"] 无法触发问题解决方案

    鄙人才疏学浅,新人一枚,不足之处还请谅解,写下这个也只是为了给大家分享一下我解决这个BUG的方法,也是自己的一个笔记. 首先,我们使用fastclick插件的初衷是解决“tap”事件“点透”的BUG: ...

  5. js javascript:void(0) 真正含义

    我想使用过ajax的都常见这样的代码:<a href="javascript:doTest2();void(0);">here</a>但这儿的void(0) ...

  6. WPF中的瀑布流布局(TilePanel)控件

    最近在用wpf做一个metro风格的程序,需要用到win8风格的布局容器,只能自己写一个了.效果如下 用法 : <local:TilePanel                          ...

  7. c位段

    假如程序表示四盏灯的开关状态灯只有开或关两种状态所以用1和0就可以表示为了节省内存就用一个二进制位表示一盏灯这里就定义位域用 a b c d 各表示一盏 这里定义时注意选用无符号类型位域允许用各种格式 ...

  8. 单例模式(Singleton)的6种实现

    1.1.1 摘要 在我们日常的工作中经常需要在应用程序中保持一个唯一的实例,如:IO处理,数据库操作等,由于这些对象都要占用重要的系统资源,所以我们必须限制这些实例的创建或始终使用一个公用的实例,这就 ...

  9. Ubuntu中NetBeans C/C++配置、编译

    系统环境:Ubuntu 9.04软件环境:NetBeans 6.7.1 C/C++ .JDK1.6.0_16本次目的:完成NetBeans 6.7.1 C/C++ 的配置工作.编译测试及对中文支持 首 ...

  10. 收起虚拟键盘的各种方法 -- IOS

    使用虚拟键盘来输入资讯,是 iOS 的重要互动方式之一,虚拟键盘通常会自动出现在可以编辑的 UITextField 或是 UITextView 的编辑事件中,叫出键盘固然容易,但是要把它收起来,可就没 ...