Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5654697
  • 博文数量: 291
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 7924
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-06 14:28
个人简介

阿里巴巴是个快乐的青年

文章分类

全部博文(291)

文章存档

2018年(21)

2017年(4)

2016年(5)

2015年(17)

2014年(68)

2013年(174)

2012年(2)

分类: C/C++

2013-07-01 16:24:58

一、C风格强制转换       
        C风格的转型动作主要有如下两种形式:
        (T)expression        //将expression转型为T
        T(expression)        //将expression转型为T(函数风格)
        这两种形式并无差别,只是小括号摆放位置不同而已,这两种形式为旧式转型(old-style casts)。
        C++还提供了四种新式转型,常常被称为new-style或C++-style casts:
        const_cast(expression)
        static_cast(expression)
        dynamic_cast(expression)
        reinterpret_cast(expression)
        这四种方式各有不同目的,下面详细解说。

二、const_cast
        const_cast通常被用来将对象的常量性转除(cast away the constness),它也是唯一有此能力的C++-style转型操作符。简单来说就是去掉const属性,比如:
        const int i = 1;
        int j = const_cast(i);

static_cast
        static_cast用来强迫隐式转换(implicit conversions),简单来说就是基本类型转换,比如:
        int i = 2;
        double d = static_cast(i);        //基本类型转换
        但是需要注意一下几点:
        (1)子类指针转换为父类指针是安全的,但是父类指针转换为子类指针时不安全的(建议用dynamic_cast),具体例子见后文。
        (2)不能进行无关类型指针之间的转换,即非父类和子类之间的转换,但可以将任何类型的指针转换成void类型指针,比如:
        int i = 3;
        int *pi = &i;
        double *pd = static_cast(&i);        //无关类型指针转换,编译错误
        void *pv = static_cast(pi);                //任意类型转换成void类型

四、dynamic_cast
        dynamic_cast主要用来执行“安全向下转型”(safe downcasting),也就是用来决定某对象是否归属继承体系中的某个类型,它是唯一无法由旧式语法执行的动作,也是唯一可能耗费重大运行成本的转型动作。简单来说就是多态类(父子类)之间的类型转换,比如:
        class Base {
        public:
                int m_iTest;
                virtual void TestFunc() {};         //基类必须有虚函数,保持多态性才能使用dynamic_cast                       
        };
        class Derived : public Base {
        public:
               char *m_szTest[256];
                void TestSon() {};  
        };
        Base *pb1 = new Derived();
        Derived *pd1 = static_cast(pb1);        //子类转换为父类,静态类型转换,正确但不推荐
        Derived *pd2 = dynamic_cast(pb1);    //子类转换为父类,动态类型转换,正确
        Base *pb2 = new Base();
        Derived *pd3 = static_cast(pb2);        //父类转换为子类,静态类型转换,不安全,由于切割导致访问子类成员变量时越界
        Derived *pd4 = dynamic_cast(pb2);    //父类转换为子类,动态类型转换,安全,结果为NULL 
        需要注意的是:首先,要保证基类有虚函数即有多态性才能使用dynamic_cast;其次,要判断转换结果是否为NULL,否则后果自负。
     
五、reinterpret_cast   
        reinterpret_cast意图执行低级转型,实际动作及结果可能取决于编译器,这也就表示其不可移植。简单来说就是不同类型的指针类型转换,具体如下:
        (1)转换的类型必须是一个指针、引用、函数指针或成员指针。
        (2)在比特位级别进行转换,即可以将一个指针转换成一个整数,也可以把一个整数转换成一个指针(即先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值),但不能将非32 bit(具体位数跟平台有关,也可能是64 bit)的实例转换成指针。
        具体例子如下:
        int doSomething() {return 0;}
        typdef void (*FuncPtr)();        //函数指针类型
        FuncPtr funcPtrArray[256];     //函数指针数组
        funcPtrArray[0] = &doSomething;    //编译错误,类型不匹配
        funcPtrArray[0] = reinterpret_cast(&doSomething);    //不同函数指针类型之间强制转换

六、总结
1、新旧转型选择
        旧式转型任然合法,但新式转型较受欢迎,原因有二:
        (1)它们很容易在代码中被辨识出来(不论是人工辨识或使用工具如grep),因而得以简化“找出类型系统在哪个地点被破坏”的过程。
        (2)各转型动作的目标愈窄化,编译器愈可能诊断出错误的运用。
2、转型副作用
        无论哪种类型的转型都会带来性能的损失,因此:
        (1)如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_cast,如果有个设计需要转型动作,试着发展无需转型的替代设计。
        (2)如果转型是必要的,试着将它隐藏于某个函数背后,调用者随后可以调用该函数,而不需将转型放进它们自己的代码内。


        
阅读(2230) | 评论(1) | 转发(0) |
1

上一篇:C++之explicit

下一篇:C++之inline函数

给主人留下些什么吧!~~