C++中的dynamic_cast和static_cast转化

一、先说C语言,C语言中有两种类型转化:

(1)隐式转化

int i;
float j = i;

(2)显式转化

void *p;
int *a = (int*)p

二、谈一谈C++中的两种标准类型转化:static_cast、dynamic_cast

C++作为C语言的扩展仍然支持C语言中原有的类型转化方式,但是由于多加了“类“,所以C++对于类型转化需要更高的安全保障。

C++中共有四种标准类型转化:(static_cast,dynamic_cast,const_cast,reinterpret_cast)

(1)static_cast,发生在编译期

a)在进行基本数据类型(int, float...)之间的转化时的效果和显示转化的效果相同

float i = 2.1;
int j = (int)i;
int j = static_cast<int>(i);
<span style="font-family: Arial, Helvetica, sans-serif;">输出后都为:2</span>
b)基类与子类之间指针的类型转化,使用static_cast可以在一个继承树内自由转化,没有关系的两个类指针之间的转化会报错

上行转化:子类-->基类(安全)

下行转化:基类-->子类(不安全)

class A {};
class B {};
class C:public B{}

B *b;
A *a = static_cast<A*>b; //会直接报错,因为A和B之间并没有关系
C *c = static_cast<C*>b; //不会报错,但是这种转化不安全,因为b可能只是B的指针

(2)dynamic_cast,发生在运行期

这是C++为了保证向下的类型转化安全而设置的转化方式。

使用dynamic_cast动态转化要求类中必须有虚函数,因此我觉得dynamic转化是根据虚函数表来确定转化类型是否安全的。

使用dynamic_cast转化,它会在运行期间进行类型转化,如果目标类型和源类型不是同一类型,则返回null值。

class People
{
    virtual void fun()
    {
         std::cout<<"People::fun"<<std::endl; 
    }
}

class Student:public <span style="font-family:Arial, Helvetica, sans-serif;">People</span>
{
    void fun()
    {
         std::cout<<"Student::fun"<<std::endl;
    }
}

class Teacher:pubic <span style="font-family: Arial, Helvetica, sans-serif;">People</span>
{ 
    void fun()
    {
        std::cout<<"Teacher::fun"<<std::endl;
    }
}<pre name="code" class="cpp">class Other {
    
public:
    virtual void func()
    {
        cout<<"Other::func()"<<endl;
    }
};

using namespace std;
int main(void)
{ 
     People *pe = new Student;
     Teacher* dy_te = dynamic_cast<Teacher*>(pe);
     Teacher* st_te = static_cast<Teacher*>(pe); 
     cout << "dy_te: " << dy_te << endl;
     cout << "st_te: " << st_te << endl;// dy_te->fun(); //pe绑定的是Student而不是Teacher,dy_te为0,调用此句会失败 
     st_te->fun(); // pe绑定的是Student而不是Teacher,st_te不识别这些, 而是当做red的函数来处理! 

     Other* _other = new Other; 
     Teacher* dy_tee = dynamic_cast<Teacher*>(_other);// 
     Teacher* st_tee = static_cast<Teacher*>(_other);// _other绑定的是other而不是Teacher,编译的时候失败 
     Teacher* t = (Teacher*)_other; t->fun(); 
     cout << "t: " << t << endl; 
     cout << "dy_tee"<< dy_tee << endl;
     delete pe; delete _other;
     pe = NULL;
     _other = NULL; 
     return 0;
}


 终端输出的值如下: 
dy_te: 0x0
st_te: 0x100105510
Stuent::fun()
Other::func()
t: 0x100105520
dy_tee: 0x0

参考了另一篇博客http://windsplife.blogspot.com/2010/09/cstaticcast-dynamiccast-reinterpretcast.html后发现dynamic_cast还可以抛出std::bad_cast异常

其具体例子如下:

#include <iostream>
#include <typeinfo>
using namespace std;
 
class Base {
public:
    virtual void foo() = 0;
};
 
class Derived1 : public Base {
public:
    void foo() {
        cout << "Derived1" << endl;
    }
 
    void showOne() {
        cout << "Yes! It's Derived1." << endl;
    }
};
 
class Derived2 : public Base {
public:
    void foo() {
        cout << "Derived2" << endl;
    }
  
    void showTwo() {
        cout << "Yes! It's Derived2." << endl;
    }
}; 
 
void showWho(Base &base) {
    try {
        Derived1 derived1 = dynamic_cast<derived1&>(base);
        derived1.showOne();
    }
    catch(bad_cast) {
        cout << "bad_cast 轉型失敗" << endl;
    }
}
 
int main() { 
    Derived1 derived1;
    Derived2 derived2;
 
    showWho(derived1);
    showWho(derived2);
 
    return 0;
}

注: 在<Google C++代码规范>中, google内部约定: 除单元测试外, 不要使用 dynamic_cast, 如果你需要在运行时确定类型信息,  说明设计有缺陷 .

具体的讨论可参见:http://www.zhihu.com/question/22445339

完成这篇文章参考了以下资料:
http://www.cnblogs.com/weidagang2046/archive/2010/04/10/1709226.html

http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used

http://blog.sina.com.cn/s/blog_5a48dd2d0101cnzr.html

剩下的两种标准类型转化将会在以后在进行研究。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值