C++学习笔记(八)类型转换

  表达式是否合法,取决于操作数的类型, 而且合法的表达式其含义也由其操作数类型决定。
  在C++中,某些类型之间存在相关的依赖关系。
  如果两种类型 相关,则可在需要某种类型的操作数位置上, 使用该类型的相关类型对象或值
  所谓相关,指的就是两种类型可以互相转换。

  考虑一下例子:
    int ival = 0;
    ival = 3.541 + 3;
   则ival的值 为 6
   
  这种是把等式右边的操作按精度最高处理,然后强制转为左边的类型。这两种都是隐式类型转换

  C++定义了算术类型之间的内置转换以尽可能防止精度损失

   那么,何时发生隐式类型转换
   编译器在必要时将类型转换规则应用到内置类型和类类型的对象上。 
   
    1  int ival;
        double dval;
        ival >= dval;  int 转为double
       在混合类型的表达式中,其操作数被转换为相同的类型,一般会往高精度转换。
 
    2  用作条件的表达式被转换为bool类型
       int ival;
       if(ival)
       while(cin)
       这些可以将 表达式转换为bool类型。

        1 赋值时的强制类型转换
        2 函数调用时的转换
        这些转换都需要类型之间相互兼容  

   算术转换
     算术转换规则定义了一个类型转换层次, 将二元操作符的两个操作数转换为同一类型, 并使表达式的值也具有相同类型。在包含多种类型的表达式中,转换规则要确保计算值的精度。

     最简单的转换为整形提升: 对于所有比int小的整形,包括char、 signed char、short 和unsigned short, 如果他们的所有可能的值都包容在int 内,那么它们就会被提升为int型。否则,它们将被提升为unsigned int。 bool值 false转换为0, true转换为1.
  
    有符号与无符号类型之间的转换
    若表达式中使用了无符号(unsigned)数值, 所定义的转换规则需保护操作数的精度。确保精度,就是说,表示范围低的类型要向表示范围高的类型转。
     unsigned 操作数的转换依赖于机器中整形的相对大小。因此,这类转换本质上依赖于机器。

     转换规则,如果 int型足够表示所有unsigned short型的值,则将unsigned short转换为int , 否则,将两个操作数均转换为unsigned int。  如果short用半字表示而 int用一个字表示, 则所有的unsigned值都能包容在int内。 
   
    对于包含signed和unsigned int 型的 表达式, 其转换可能出乎我们的意料,表达式中 的signed 型数值会被转换为unsigned型。 
     如果 int型的值为负数,则可以将其转换为unsigned int对应的机器码,然后跟另一个 unsigned int型的值相加,如果产生溢出, 则会结果错误。丧失精度

 2   理解算术转换
     提升与转换
       提升 就是将一个低于CPU处理位数的数值,提升为CPU处理的位数。
      而转换,就是讲一个CPU处理位数的数值转换为大于CPU处理的位数的数值
  其他隐式转换

     1  指针转换
      大多数情况下,数组都会自动转换为指向第一个元素的指针。只有一下几种情况例外:
       数组用作取地址& 操作符的操作数 ; sizeof操作符的操作数时。 用数组对数组的引用进行初始化时。 用数组对数组的引用进行初始化

   关于  判断语句中的非bool类型向bool类型,及 bool与其它类型的转换,就不一一说了
  
下面重点看下, 转换与枚举类型
    C++自动将枚举类型的对象或枚举成员转换为整形, 其转换结果可用于任何要求使用整数值的地方

     enum Points { point2d=3, point2w, point3d=3, point3w};

    const size_t array_size = 1024
   int chunk_size = array_size * pt2w;
   
      转换为const对象
     当使用非const对象初始化const对象的引用时, 系统将非const对象转换为const对象。  此外,还可以将非const对象的地址,转换为指向相关const类型的指针

    int i;
    const int ci = 0;
    const int &j = i;
    const int *p = &ci;

    由标准库类型定义的转换
    从istream中读取数据,并将此表达式作为while循环条件:
    string s;
    while(cin>>s);
    这里使用了IO标准库定义的类型转换。  cin>>s, 无论读入成功与否,该表达式的结果都是cin。
     while循环条件应为bool类型的值。所以,这里,istream类型的值应转换为 bool类型。 将istream类型转换为bool类型意味着要检验流的状态: 如果最后一次读cin 的尝试是成功的,则流的状态将导致上述类型转换bool类型后获得true值。反之,获得false值


     显示转换:它也称为强制类型转换:cast
     强制类型转换的操作符有:
     static_cast, dynamic_cast, const_cast, reinterpret_cast

      何时需要强制类型转换
     命名的强制类型转换:
       cast-name<type>(expression)
      其中,cast-name有如下几种:
        dynamic_cast:
              支持运行时识别指针或引用所指向的对象。
        const_cast
            const char *pc_str;
            char *pc = string_copy(const_cast<char*>(pc_str));

        static_cast:  是将高精度的值转为低精度的值,这样做的好处是, 可以告诉编译器或读者,可以不用担心精度损失,而放心的去执行。
        也可以找回原来精度的值
       void *p = &d;
       double *dp = static_cast<double*> (p);

       reinterpret_cast
      这个可以将任意类型转换为任意类型, 但是转换后的类型其实扔属于原先被转换的类型:如下所示,
     int *ip;
     char *pc = reinterpret_cast<char *>(ip);
     其实,在这里,pc扔属于int类型,所以不能再进行一下操作: string_copy(pc);
     那么,这个强制转换存在的意义为何呢?
       它其实,是在要对某一中类型进行操作时,如果这种操作用另一种类型更加简单,那么便可以先用该语句,将其转换为该类型

      建议: 避免使用强制类型转换:
      强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的C++程序。

   旧式强制类型转换:
     显示强制类型转换用圆括号将类型括起来实现:
       char *pc = (char *) ip;
       这种强制类型转换的可视性比较差,其效果与使用reinterpret_cast符号相同, 难以跟踪错误的转换。
       
     用C++命名式的强制类型转换的好处是:
     可以让程序员清楚的辨别 各个强制类型转换的风险等级。
        最有风险的是: reinterpret_cast, 其次是 const_cast,  再次是static_cast.   dynamic_cast是最特殊的一个:
   dynamic_cast运算符,应该算是四个里面最特殊的一个,因为它涉及到编译器的属性设置,而且牵扯到的面向对象的多态性跟程序运行时的状态也有关系,所以不能完全的使用传统的转换方式来替代。但是也因此它是最常用,最不可缺少的一个运算符。

    与static_cast一样,dynamic_cast的转换也需要目标类型和源对象有一定的关系:继承关系。 更准确的说,dynamic_cast是用来检查两者是否有继承关系。因此该运算符实际上只接受基于类对象的指针和引用的类转换。从这个方面来看,似乎dynamic_cast又和reinterpret_cast是一致的,但实际上,它们还是存在着很大的差别。

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值