zoukankan      html  css  js  c++  java
  • C++ cast

    excerpted from Type conversions 

    K&R Section 2.7 p59 对type conversion 的解释:

      The precise meaning of a cast is as if the expression were assigned to a variable of the specified type, which is then used in place of the whole construction.

      (类型名) 表达式

      将被转换的表达式赋值给指定类型的变量,然后用该变量替代上述语句

    PART I  Implicit conversion 隐式转换

    1. fundamental data types  基本类型   (numeric, bool, some pointer)

      精度损失:  double -> int

    2. non-fundamental types 非基本类型 

      1. NULL指针可以转换为任意类型

      2. 任何类型指针可以转换为void *

      3. 指针向上转换: 指针派生类的指针可以转换为其基类的指针

        (注: pointers to a derived class can be converted to a pointer of an accessible and unambiguous base class, without modifying its const or volatile qualification.)

    3. 类的的隐式转换

      1.单参数构造函数 

      2.赋值运算符

      3.类型转换运算符

    PART II 显示转换

    1. explicit 关键字, 防止不必要的隐式转换

        explicit  构造函数(...)    /*  在构造函数之前加explicit */

    2. type casting 

      ("coerced")   强制 

      convert any pointer into any other pointer type  任意类型转换为其它任意类型 

      1. functional notaion:  y = int (x);

      2. c-like notaion:    y = (int)x;

    3.   casting operators 运算符 用来控制类的转换 (多涉及指针和类)

      4种运算符  动态,静态,

      1.dynamic_cast      

        两种转换:

         upcast (converting from pointer-to-derived to pointer-to-base)

         downcast (convert from pointer-to-base to pointer-to-derived)

         dynamic_cast can only be used with pointers and references to classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type.

        只能用于指针和引用 或 void *,确保转换结果指向目标类型的完整的合法的对象  (type-safety checks 类型安全检查)

    //示例代码
    //
    dynamic_cast #include <iostream> #include <exception> using namespace std; class Base { virtual void dummy() {} }; class Derived: public Base { int a; }; int main () { try { Base * pba = new Derived;     Base * pbb = new Base; Derived * pd; pd = dynamic_cast<Derived*>(pba);        // 转换成功, 因为pba指向完整的Deived对象 if (pd==0) cout << "Null pointer on first type-cast. "; pd = dynamic_cast<Derived*>(pbb);        // 转换失败,返回NULL pbb指向基类对象 如果是转换引用(reference)类型失败,则抛出异常 bad_cast if (pd==0) cout << "Null pointer on second type-cast. "; } catch (exception& e) {cout << "Exception: " << e.what();} return 0; }

      requires Run-Time Type Information (RTTI) to keep track of dynamic types

      2.static_cast 类似于dynamic_cast, 可以upcast和downcast,但不做type-safety checks(交由程序员决定,因此省去了检查的开销(overhead))

    class Base {};
    class Derived: public Base {};
    Base * a = new Base;
    Derived * b = static_cast<Derived*>(a);     // 合法的代码, 但可能在解引用指针时导致runtime errors

        void *转换为任意类型

        整形值,浮点值,枚举类型转为枚举类型

      3.reinterpret_cast 从任意类型到任意类型,即使类型毫不相关,既不检查指针指向的对象,也不检查指针的类型.

        converts any pointer type to any other pointer type

        The operation result is a simple binary copy of the value from one pointer to the other.操作结果就是简单的对指针按位复制

    class A { /* ... */ };
    class B { /* ... */ };
    A * a = new A;
    B * b = reinterpret_cast<B*>(a);    // 代码合法, 但don't make sense.  解引用b将是不安全的.    

      4.const_cast

        对指针的const的操作,加上const或者去除cosnt

        作用:将一个const指针传给非const的形参     

    // const_cast
    #include <iostream>
    using namespace std;
    
    void print (char * str)    // 如果传入一个const指针, 不经转换的话会报错
    {
      cout << str << '
    ';
    }
    
    int main () {
      const char * c = "sample text";
      print ( const_cast<char *> (c) );    // 相当于传入了移除const的临时变量作为参数, 但如果函数写指针指向的对象将导致未定义的行为
      return 0;
    }

     PART III

      typeid运算符, 检查表达式的类型

        typeid (expression)

       返回值:typeinfo类型的常量, typeinfo定义在<typeinfo>头文件中

        通过==和!=比较typeinfo类型的变量

        通过成员函数name()返回描述数据类型名或类名的字符串

    // typeid
    #include <iostream>
    #include <typeinfo>
    using namespace std;
    
    int main () {
      int * a,b;
      a=0; b=0;
      if (typeid(a) != typeid(b))            //可以通过==和!=比较typeinfo类型的变量
      {
        cout << "a and b are of different types:
    ";
        cout << "a is: " << typeid(a).name() << '
    ';
        cout << "b is: " << typeid(b).name() << '
    ';
      }
      return 0;
    }
    a and b are of different types:
    a is: int *
    b is: int  

        When typeid is applied to an expression whose type is a polymorphic class, the result is the type of the most derived complete object

        当typeid用于多态类型时,结果是最接近派生的类的类型

    // typeid, polymorphic class
    #include <iostream>
    #include <typeinfo>
    #include <exception>
    using namespace std;
    
    class Base { virtual void f(){} };
    class Derived : public Base {};
    
    int main () {
      try {
        Base* a = new Base;
        Base* b = new Derived;
        cout << "a is: " << typeid(a).name() << '
    ';
        cout << "b is: " << typeid(b).name() << '
    ';
        cout << "*a is: " << typeid(*a).name() << '
    ';
        cout << "*b is: " << typeid(*b).name() << '
    ';
      } catch (exception& e) { cout << "Exception: " << e.what() << '
    '; }
      return 0;
    }
    a is: class Base *
    b is: class Base *
    *a is: class Base
    *b is: class Derived
  • 相关阅读:
    Spring Boot应用程序属性
    Spring Boot Bean和依赖注入
    Spring Boot构建系统
    Spring Boot Tomcat部署
    Spring Boot引导过程
    Spring Boot快速入门
    Spring Boot简介
    eclipse中将项目打包成jar的两种方法,及其问题与解决方法
    配置Zuul代理下游的认证
    WireMock和Spring MVC模拟器
  • 原文地址:https://www.cnblogs.com/longwaytogo/p/6138937.html
Copyright © 2011-2022 走看看