dynamic_cast的使用条件

本文详细解析了C++中dynamic_cast的使用条件,包括虚函数表的作用,并通过代码实例展示了如何利用dynamic_cast访问派生类新增的public成员。同时,文章还讨论了dynamic_cast转化失败的判断方法及对其实现的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天从学长那里听来一道腾讯的面试题,问的是C++中的dynamic_cast在什么情况下是错误的?我认为这个问题的更好的描述是dynamic_cast的使用条件是什么?

C++提供了两种方式来支持RTTI,dynamic_cast是其中一种,另一种是typeid()。表面上看,dynamic_cast有两种形式:

Base *pBase = new Derived();

Derived *pDerived = dynamic_cast<Derived *> pBase;


Base refBase = Derived();

Derived &refDerived = dynamic_cast<Derived &> refBase


即dynamic_cast用于将基类的引用或指针转化为派生类的引用或指针。但使用条件是:1、基类的指针或引用确实绑定到派生类的对象上;2、只有当基类至少含有一个虚函数的时候才能使用dynamic_cast。原因是RTTI机制依赖于虚函数表(inside C++ object model第一章给出了解释),而dynamic_cast是RTTI的一种,所以必须要有虚函数表的支持,也就是要虚类中至少有一个虚函数。

那么,dynamic_cast有什么好处呢?

我们知道,基类的指针即使指向的是派生类的对象,但通过基类的指针也只能访问到基类中包含的public成员,那如果想要访问派生类中新增的public成员呢?这就需要将基类的的指针动态类型转化为派生类的指针。见以下代码:

#include<iostream>
using namespace std;
class base{
public:
    base(int x):a(x){ }
    virtual void fcn(){ }  //要有虚函数
    int a;
};

class derived:public base{
public:
    derived(int x,int y):base(x),b(y){ }
    int b;
};

int main(){
    base *pbase = new derived(100, 200);
    cout << pbase->a << endl;
    //cout << pbase->b << endl;  //不能通过基类的指针访问派生类新增的public成员
    
    derived *pderived = dynamic_cast<derived *>(pbase);
    
    cout << pderived->a << endl;
    cout << pderived->b << endl;
}

如何对dynamic_cast转化是否成功进行判断,从而选择进行基类的操作还是进行派生类的操作呢?见下面的代码:

#include<iostream>
using namespace std;
class base{
public:
    base(int x):a(x){ }
    virtual void fcn(){ }  //要有虚函数
    int a;
};

class derived:public base{
public:
    derived(int x,int y):base(x),b(y){ }
    int b;
};

int main(){
    base *pbase0 = new base(100);
    base *pbase1 = new derived(100, 200);


    if(NULL != dynamic_cast<derived *>(pbase0)){
        cout << dynamic_cast<derived *>(pbase0)->b << endl;
        cout<<"derived"<<endl;
    }else{
        cout << pbase0->a << endl;
        cout<<"base"<<endl;
    }

    if(derived *pderived = dynamic_cast<derived *>(pbase1)){
        cout << dynamic_cast<derived *>(pbase1)->b << endl;
        cout<<"derived"<<endl;
    }else{
        cout << pbase1->a << endl;
        cout<<"base"<<endl;
    }
}
运行结果如下:

100
base
200
derived

《C++ primer》第5版P731上给出了以下代码框架:

if(Derived *dp = dynamic_cast<derived *>(bp)){

//使用bp指向的Derived对象

}else{

//使用bp指向的Base对象

}

在vs和gcc下测试过:如果bp指向的不是派生类的对象而是基类的对象的话,那么两种编译器下都不能通过编译!!!这样的运行时动态类型判断也就没有意义了。这种写法值得商榷!


如果是引用的话,当转化不成功时会抛出std::bad_cast异常,详见《C++ primer》第5版P731。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值