美文网首页
C++类型转换的初步研究

C++类型转换的初步研究

作者: 狗子孙 | 来源:发表于2018-09-14 22:48 被阅读3次

    C风格的类型转换

    C风格类型转换包括隐式和显式(强制)。如int a = 2.5float a = (float)1等,针对赋值、函数调用、返回值等情况,常见类型可以进行自动的类型转换,转换方式通常是有意义的,例如浮点型转换为整形,会截掉浮点部分,char型转换成整形会按照ASCII码排序等,隐式类型转换通常按照提升原则,把较小的类型如char提升到较大的类型如int再做进一步操作。

    类型转换的提升

    static_cast

    类似C风格的静态类型强制转换,适用于:

    1. 基础类型转换
    2. 基类转子类(不安全),子类转基类(安全)
    3. 任意表达式转void指针
    int a = 0;
    int b = static_cast<int>(2.5);     // 正确,基础类型转换
    int *c = &a;
    float *d = static_cast<float*>(c); // 错误,无关类型转换
    void *e = static_cast<void*>(c);   // 正确,任意类型转空指针
    

    上面提到了静态类型和动态类型,一个对象(变量)的静态类型就是其声明类型,如表达式int a中的int就是对象a的声明类型,即静态类型;而一个对象(变量)的动态类型就是指程序执行过程中对象(指针或引用)实际所指对象的类型,如Base* pB = new Drived; 其中class Drived继承于class Base,则指针对象pB的静态类型就是Base(声明类型),动态类型就是Drived(实际所指对象的类型),又如Base* pB = new Base;此时指针对象pB的静态类型和动态类型也是相等的,都是Base。对于动态类型我们需要下面的dynamic_cast。

    dynamic_cast

    有条件的动态类型转换,适用于:

    1. 基类和子类之间的安全转换(基类必须要有虚函数)
    2. 相同基类不同子类的类型转换
    class BaseClass {
    public:
        virtual void foo() {}; //基类必须有虚函数,否则dynamic_cast编译错误
    };
    
    class DerivedClass : public BaseClass {
    };
    
    BaseClass* pb = new DerivedClass();
    DerivedClass *pd1 = static_cast<DerivedClass *>(pb);    //子类->父类,静态类型转换,正确但不推荐
    DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb);   //子类->父类,动态类型转换,正确
    
    BaseClass* pb2 = new BaseClass();
    DerivedClass *pd21 = static_cast<DerivedClass *>(pb2);  //父类->子类,静态类型转换,危险
    DerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2); //父类->子类,动态类型转换,结果是NULL
    

    reinterpret_cast

    用来处理无关类型间的转换,随便搞,编译都没问题,但是后面不一定能用。适用于:

    1. 整形和指针间
    2. 函数指针之间
    3. 对象指针之间
    4. 类成员函数指针之间
    5. 类成员变量指针之间

    直观上reinterpret_cast好像没什么用,因为转换类型过后大概率不能用,还是得转回原先的类型才能用。下面是一个很直(wu)观(liao)的例子

    #include <iostream>
    // 返回一个地址的哈希值
    // 不必在意地址所存放的具体类型和含义
    unsigned short Hash(void *p) {
        unsigned int val = reinterpret_cast<unsigned int>(p);
        return (unsigned short)(val ^ (val >> 16));
    }
    using namespace std;
    int main() {
        int a[20];
        for (int i = 0; i < 20; i++)
            cout << Hash(a + i) << endl;
    }
    

    const_cast

    const_cast用于去除变量的常量(只读)属性,也是唯一可以达到这个目的的转换方式。例如:

    int a = 1;
    const int* b = &a;
    *b = 2;     // 错误,const对象
    int *c = const_cast<int *>(b);
    *c = 3;     // 正确,const已解除
    

    类型转换运算符

    类成员的重载运算符,类似operator int();的形式,隐式类型转换时会调用,跟上面的几个关系不大,在这里就mark一下,有机会拓展。

    参考

    C++类型转换总结
    浅谈C/C++的浮点数在内存中的存储方式

    相关文章

      网友评论

          本文标题:C++类型转换的初步研究

          本文链接:https://www.haomeiwen.com/subject/tvwawftx.html