C++:详解显式类型转换

简介: C++:详解显式类型转换

C++ 与 C 强制类型转换的区别

  • C 可以在任意类型之间转换,不安全;C++ 相对比较安全。
  • C 难以查询定位。C++ 易于追踪,grep -rn "cast-name"

语法形式:

cast-name <type> (expression)

1 、static_cast

基础类型间的转换

  • 基本数据类型间的转换,不能用于无关类型的转换。
  • void 指针转换成目标类型的指针,任何类型的表达式转换成 void 类型。
double d = static_cast<int>(i);             // ok, 用于基本数据类型间的转换
 int *pInt = static_cast<int*>(pVoid);       // ok,void 指针转换成目标类型的指针
 float *pFloat = static_cast<float *>(pInt);  // error,不能用于无关类型转换,不同指针类型间转换

2、dyamic_cast

用于下行转换(基类 -> 派生类),运行时动态检查。

类继承中的类型转换

  • 上行转换:派生类 -> 基类,派生类指针或引用转换成基类指针或引用,安全。
  • 下行转换:基类 -> 派生类,基类指针或引用转换成派生类指针或引用,不安全,需要动态类型检查 dyamic_cast,这是因为基类指针和引用可能指向的并不是一个子类对象。
// 同时完成类型转换和条件检查两个任务
 // 1、转换成功
 if (Derived *dp = dynamic_cast<Derived*>(bp)) {
     // 使用 dp 指向派生类对象
 }
 // 2、转换失败
 else {
     // 使用 bp 指向的基类对象
 }

3、const_cast

移除类型的 const 或 volatile 属性。将常量对象转换成非常量对象。

const int number = 100;
 int *pInt2 = const_cast<int *>(&number);  // ok,但是通过 pInt2 写值是未定义的行为 *pInt2 = 200

上述例子中提到的未定义的行为,const_cast 不是为了改变常量的值而设计的。话句话说,要修改值,一开始就应该定义为变量,何必多此一举定义为常量。const_cast 用于有函数重载的上下文中,例如:

const string &shorterString(const string &s1, const string &s2) {
     return s1.size() <= s2.size() ? s1 : s2;
 }

若对两个非常量的 string 实参调用这个函数,但是返回结果仍然是 const string 的引用。因此我们需要重载该函数,当实参不是常量的时候,返回普通引用。

string &shorterString(string &s1, string &s2) {
     // 实参强制转换成对 const 的引用,调用 shorterString 函数的 const 版本
     auto &r = shorterString(const_cast<const string&>(s1), const_cast<const string&>(s2));
     // 将返回的 const string 引用转换为普通的 string &
     return const_cast<const string&>(r);
 }

const_cast 用于函数重载,其他情况下使用则说明程序存在着某种设计缺陷。

4、reinterpret_cast

为运算对象的位模式提供较低层次上的重新解释。该运算符可以用来处理无关类型之间的转换,例如任意指针(引用)类型之间的转换。效果等同于 C 语言风格的强制类型转换。这样可能会导致未定义的行为,例如数字类型转换为指针类型。不同于 static_cast,使用 reinterpret_cast 没有安全检查,这一点要尤其小心。

相关文章
|
7月前
|
安全 编译器 程序员
【C++】C++的类型转换
【C++】C++的类型转换
|
7月前
|
设计模式 安全 算法
【C/C++ 类型转换 】深入理解C++向上转型:从基础到应用
【C/C++ 类型转换 】深入理解C++向上转型:从基础到应用
234 0
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
105 5
|
2月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
31 1
|
7月前
|
存储 安全 编译器
C++:现代类型转换
C++:现代类型转换
58 5
|
2月前
|
存储 编译器 数据安全/隐私保护
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解2
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
44 3
|
2月前
|
编译器 C++
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解1
【C++篇】C++类与对象深度解析(四):初始化列表、类型转换与static成员详解
55 3
|
2月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
30 0
|
5月前
|
存储 安全 编译器
【C++11】类型转换
【C++11】类型转换
40 0
|
5月前
|
安全 程序员 编译器
C++一分钟之-C++中的类型转换
【7月更文挑战第8天】C++中的类型转换涉及隐式和显式操作,隐式转换如从`int`到`double`是自动的,但可能导致数据丢失。显式转换包括`static_cast`, `dynamic_cast`, `const_cast`, `reinterpret_cast`,以及转换构造函数。要避免数据丢失、类型不匹配和运行时错误,需谨慎使用显式转换并检查结果。过度使用`reinterpret_cast`应避免。理解这些转换有助于编写更安全的代码。
49 0