曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 3581|回复: 0
打印 上一主题 下一主题

dynamic_cast -- 运行时强制转换

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-12-5 22:06:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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 ,那么:
[C++] 纯文本查看 复制代码
Base *bp, b_ob;
Derived *dp, d_ob;

bp = &d_ob;           // 基类型的指针可以指向派生类的对象

dp = dynamic_cast<Derived *> (bp);   //强制转换基类指针为派生类指针,做法正确

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

下面的是强制转换失败的示例:
[C++] 纯文本查看 复制代码
bp = &b_ob;
dp = dynamic_cast<Derived *>(bp);    //错误

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

下面是代码测试多种 dynamic_cast 的情况:
[C++] 纯文本查看 复制代码
// 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
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-17 20:55 , Processed in 0.082384 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表