C++类型转换之static_cast和dynamic_cast

1. static_cast

(1)用于基本的数据类型转换

test_enum type = test_enum_1;

char a ;
int b = static_cast<int>(a);
char c = static_cast<char>(b);
type = static_cast<test_enum>(b);

char* pa = NULL;
int *pb = (int*)pa;
//int *pb = static_cast<int*>(pa);        //error
//pa = static_cast<char*>(pb)           //error
char *pc = (char*)pb;
//char *pc = static_cast<char*>(pb);    //error

void *p = static_cast<void*>(pa);
pb = static_cast<int*>(p);
pc = static_cast<char*>(p);

(2)类层次中基类与子类成员函数指针的转换

class A
{

public:
    void set(){}
};

class B:public A
{
public:
    void set(){}
};

typedef void (A::*PS_MFunc)();        //指向类A的成员函数指针

PS_MFunc func = &A::set;
func = static_cast<PS_MFunc>(&B::set); //基类指向子类成员函数指针,必须进行转换

(3)类层次结构中基类与子类指针或引用之间的转换

  上行转换:子类指针或引用转换成基类表示——安全
  下行转换:基类指针或引用转换成子类表示——危险(没有动态类型检查)

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

A objA;
B objB;
A* pObjA = new A();
B* pObjB = new B();
C* pObjC = new C();
D* pObjD = new D();

objA = static_cast<A&>(objB);     //转换为基类引用    
objA = static_cast<A>(objB);
objB = static_cast<B>(objA);      //error 不能进行转换  

pObjA = pObjB;                    //right 基类指针指向子类对象
//objB = objA;                      //error 子类指针指向基类对象
pObjA = static_cast<A*>(pObjB);   //right 基类指针指向子类
pObjB = static_cast<B*>(pObjA);   //强制转换 OK 基类到子类
//pObjC = static_cast<C*>(pObjB);   //error 继承于统一类的派生指针之间转换 
//pObjD = static_cast<D*>(pObjC);   //error 两个无关联之间转换

2 .dynamic_cast

(1) 继承关系的类指针对象或引用之间的转换

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

A objA;
B objB;
A* pObjA = new A();
B* pObjB = new B();
C* pObjC = new C();
D* pObjD = new D();
//objA = dynamic_cast<A>(objB);         //error 非引用

objA = dynamic_cast<A&>(objB);
//objB = dynamic_cast<B&>(objA);      //error A 不是多态类型不能转换 若有虚函数则可以进行转换

pObjA = dynamic_cast<A*>(pObjB);
//pObjB = dynamic_cast<B*>(pObjA);    //error A 继承关系 不是多态类型不能转换
//pObjB = dynamic_cast<B*>(pObjC);    //error C 兄弟关系 不是多态类型不能转换
//pObjB = dynamic_cast<B*>(pObjD);    //error D 没有关系 不是多态类型不能转换

注意:上述的下行转换时通不过的,而static_cast的下行转换时能通过的,因为dynamic_cast多了动态类型检查。

(2) 包含有虚函数之间对象指针的转换

class A
{
Public:
     Virtual ~A(){}
};
class B:public A
{
};
class C:public A
{
};
class D
{
Public:
Virtual ~D(){}
};
pObjB = dynamic_cast<B*>(pObjA);    // worning 继承关系 父类具有虚函数 多态
pObjB = dynamic_cast<B*>(pObjD);    //worning 没有关系 D是多态类型可以转换
//以上结果:pObjB == NULL 此处会发生一个运行时错误

  也就是说,除了基类指针指向子类对象可以没有虚函数外,其他要进行dynamic_cast转换必须具有虚函数才行。为什么呢?下面继续:

(3)dynamic_cast转换的安全性

  dynamic_cast是动态转换,只有在基类指针转换为子类指针时才有意义。
  子类指针转换为基类指针本来就是可以的,基类指针指向之类对象OK;但是基类指针转换为子类指针,并不是每一次都有效,只有基类指针本身指向的是一个派生类对象,然后将此基类指针转换为对应的派生类指针才是有效的。这种情况在表面上是无法判定的,此时dynamic_cast就发挥了作用。

情况1:static_cast转换

class A
{
};
class B:public A
{
public:
    int m;         //B 成员
};

A* pObjA = new A();
B* pObjB  = NULL;
pObjB = static_cast<B*>(pObjA);   //基类指针转化为子类指针 成功转换
pObjB->m = 10;                   //实际中pObj所指向的对象 是A类对象
//上面会发生什么呢,在VC6.0中正常运行。。。?

// 如果:
pobjB = dynamic_cast<B*>(objA);//error 基类A没有虚函数 不构成多态

情况2:dynamic_cast转换

class A
{
public:
   virtual ~A(){}         //虚函数 多态
};
class B:public A
{
public:
    int m;
};

A* pObjA = new A();
B* pObjB  = NULL;
pObjB = dynamic_cast<B*>(pObjA);  //编译通过 
//实际运行结果:pObjB == NULL   // dynamic_cast保证转换无效 返回NULL

dynamic_cast转换不成功则返回0;

4. 虚函数对于dynamic_cast作用

  为何使用dynamic_cast转换类指针时需要虚函数呢?
  dynamic_cast转换是在运行时转换,运行时转化就需要知道类对象的信息(继承关系等)
  如何在运行时获取到这个信息——虚函数表。
  C++对象模型中,对象实例最前面的就是虚函数表指针,通过这个指针可以获取到该类对象的所有虚函数,包括父类的。因为派生类会继承基类的虚函数表,所以通过这个虚函数表,我们就可以知道该类对象的父类,在转换的时候就可以用来判断对象有无继承关系。

所有的虚函数对于正确的基类指针转换为子类指针是非常重要的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值