🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一.类型转换 + 类型转换会生成一个新的匿名对象 ,而不是修改原有的变量。 + 类类型转换时,调用类型转换函数或转换构造函数。 ## 二.隐式类型转换 ### 1.发生的时机 + 在混合类型的算术表达式中(也叫 **算术转换** ) ```c++ 3.14159 + 25; ``` + 用一种类型的表达式初始化或赋值给另一种类型的对象。 ```c++ int a = 3.14159; ``` + 把一个表达式传递给一个函数调用,而表达式的类型与形式参数的类型不相同。 ```c++ double MySqrt( double ); MySqrt(2); ``` + 从一个函数返回一个表达式 表达式的类型与返回类型不相同。 ```c++ double fun() { return 233; } ``` ### 2.特殊类型的隐式转换 + **左值到右值** 任何非函数、非数组类型的左值(新标准为泛左值),可隐式转换成同类型的右值(新标准为纯右值)。 + **布尔转换** 在条件或需要 `bool` 的表达式中,整数、浮点、枚举、指针和成员指针转换成布尔类型。零值、`NULL` 和 `nullptr` 转换成 `false` ,其余转换成 `true` 。 > 需要注意的是,当成员指针为 `NULL` 或 `nullptr` 时,成员指针的值为 `-1` ,但会转换成 `false`。 + **数组转换成指针** 在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针。除了 `sizeof` 、 `typeid` 和取地址运算符。 > 需要注意的是,当数组作为函数参数时,编译器会将其 **替换而不是转换** 成指针。 + **函数转换成指针** 函数作为值使用时,会转换成指向函数自身的指针。非静态成员函数除外。 对于函数名(不是函数指针名) `f` ,有以下规律: ```c++ f == &f;/*true,得到的都是函数的地址*/ *f == f;/*true,得到的都是函数的地址*/ *f == &f;/*true,得到的都是函数的地址*/ ``` + **指针转换** + 指向任意非常量的指针可以转换为 `void*` + 指向任意常量的指针可以转换为 `const void*` + 常数 `0(NULL)` 和 `nullptr` 能够转换成任意指针类型。 + 公有继承中,派生类指针可以转换成基类指针。 + **成员指针转换** + 常数 `0(NULL)` 和 `nullptr` 能够转换成任意成员指针类型。此时成员指针的值为 `-1` 。 + 基类的同类型成员指针可以转换成派生类同类型成员指针。 + **常量转换** 允许非常量类型的指针或引用转换成指向相应的常量类型的指针或引用。 + **类定义的转换** 类型转换函数和转换构造函数。 ## 三.算术转换 1. 两个通用的指导原则 + 为防止精度损失,如果必要的话,类型总是被提升为较宽的类型。 + 所有含有小于整型的有序类型的算术表达式在计算之前其类型都会被转换成整型。 2. **整型提升** 在确定共同的目标提升类型之前,编译器将把小整数类型转换成整型。 其中, `bool` 、 `char` 、 `signed char` 、 ` unsigned char` 、 ` short` 和 `unsigned short` 等类型,只要它们所有可能的值都能存在 `int` 里,它们就会提升成 `int` 类型;否则提升成 `unsigned int` 型。 >[warning] 下面几种情况不属于整数提升: >+ 把小整数类型和整型转换成更大的整数类型。如 `short` 或 `int` 转换成 `long` 不属于整型提升。 >+ 小整数之间的转换。如 `char` 转换成 `short` 不属于整型提升。 >+ 整型 `int` 与 无符号整型 `unsigned` 的转换。 3. **浮点提升** `float` 类型可转换为 `double` 类型。 >[warning] 下面几种情况不属于浮点提升: > >+ 把小浮点数类型和双精度浮点型转换成更大的浮点类型。如 `float` 或 `double` 转换成 `long double` 不属于浮点提升。 4. 无符号类型的运算对象:结果依赖机器中各个整数类型的相对大小。 + 若表达式即有有符号类型,又有无符号类型,且无符号类型 >= 有符号类型,则带符号的运算对象转换成无符号类型。 ```c++ //当一个无符号数和一个负数相加时,b会转换成无符号类型(无符号最大值加上这个负数) unsigned int a = 5; int b = -6; cout<<a + b;//输出值4294967295 ``` + 若表达式即有有符号类型,又有无符号类型,且无符号类型 < 有符号类型,则带符号的运算对象转换成无符号类型。若该无符号类型的所有值都能存在于带符号类型中,则转换成带符号类型,否则转换成无符号类型。 ```c++ unsigned int e = 5; double f = -6; cout<<e + f;//输出值-1 ``` ## 四.强制类型转换 ### (一)旧式的强制类型转换 ```c++ 类型(表达式);//函数风格 (类型)表达式;//C风格 ``` ### [$](二)命名的强制类型转换 1. 格式 + **类型** 为转换的目标类型, **若为引用类型,则返回左值** 。 + **转换名称** `static_cast` `const_cast` `dynamic_cast` `reinterpret_cast` 的一种。 ``` 转换名称<类型>(表达式); ``` 2. 静态转换 `static_cast` + **适用** + 有定义不含底层 `const` 的转换。 + 不能转换类类型对象之间、类类型对象与内置类型(除了void类型)的指针。 ```c++ double slope = static_cast<double>(2020); //下面是一个错误案例 class A {}; class B {}; A *a; B *b; b = static_cast<B*>(a); ``` 3. 常量转换 `const_cast` + **适用** + 常量指针被转化成非常量指针,转换后指针指向原来的变量。 + 常量引用转为非常量引用。 + 添加const属性 >[danger]常量对象不可以被转换为非常量对象。 >[danger]试图通过指针去修改常量的内容会产生未定义的后果。 ```c++ int a = 2020; const int* aptr1 = const_cast<const int*>(&a); int* aptr2 = const_cast<int*>(aptr1); ``` 4. 重解释转换 `reinterpret_cast` + **适用** 无关类型的转换,无视大小。如指针转换成对象,指向不同类类型对象之间的指针。 >[danger]这种转换灰常危险,请慎用。 ```c++ class A {}; class B {}; A *a; B *b; b = reinterpret_cast<B*>(a); ``` 5. 动态转换 `dynamic_cast` + **适用** 将基类的指针或引用安全地转换成派生类的指针或引用。