C++兼容了C的类型转换方式,可以在C++代码中使用C风格类型转换,尤其是在大量的把C++当成C来用的项目里面,非常普遍。Modern C++提供了诸如static_cast, dynamic_cast, reinterpret_cast, const_cast的类型转换方式,在逐个讲清楚之前,先回顾一下常用的C风格的类型转换方式。

下面总结C-Style的类型转换存在的几个问题:

void foo() {
    int a = 7;
    int b = 4;
    std::cout << a / b << std::endl;

    //期待得到浮点结果的话
    std::cout << double(a) / b << std::endl; //(1)
    std::cout << double(a) / double(b) << std::endl; //(2)
}

上面代码中(2)是显式类型转换,就是告诉编译器要把a和b转换为double类型,而(1)是隐式类型转换(implicit convension),在(1)里面,b被隐式转为了double类型。

隐式类型转换带来了一个常见的问题:丢失信息。通常发生在把bit width更大的变量转换到bit width更小的变量时,例如:

void bar(char c) {
    // do somthing
}

void foo() {
    int a = 300;
    bar(a);
}

//char 的bit width容纳不下int变量的值
//所以这里就会在类型转换时丢失掉多出部分的bit信息

顺着上例,举一个负数比较的例子:

void foo() {
    int a = -1234567;
    unsigned int b = 5;
    if (a > b) {    //(1)
        std::cout << "???" << std::endl;
    }
}

在(1)这里发生了implicit convension,a被转换为了unsigned int类型,所以导致了进入if分支。只要学过计算机组成原理,自然知道正数和负数在二进制下是如何表达的,应该不难理解。

除此之外,还有很多实践中常见的隐式转换带来的问题,这里不再一一列举。
本质上,都是和bit width相关。

所以使用C-Style的类型转换,程序员需要注意:

  1. 清楚知道转换前后的两种类型的bitwidth,确保不会丢失信息
  2. 书写显式类型转换的代码,尽量避免使用隐式转换(非常不容易,这往往会发生在不经意之间,虽然很多问题都可以通过开启编译告警来提前发现-Wall,但是太多的人忽视编译器的警告)

Modern C++增加了开头提到的几种方法进行类型转换,在使用Modern C++写代码的时候,应该尽量避免使用C-Style的转换方式。


发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

我不是机器人*