65.C++的四种强制转换

65.C++的四种强制转换

显示类型转换包括静态转换(static_cast)、动态转换(dynamic_cast)、常量转换(const_cast)、重新解释转换(reinterpret_cast)

1.静态转换(static_cast)

1.1一句话说清

static_castC++ 最常用、最安全、编译期完成的类型转换运算符,用于合法的、有意义的类型转换

它是编译期检查,不会做运行时检查,比 C 语言强转 (type)val 更安全。

1.2 能做什么(最常用场景)

1.2.1 基本数据类型转换

int a = 10;
double b = static_cast<double>(a); // int → double

1.2.2 有继承关系的 向上转型(安全)

派生类 → 基类(指针 / 引用)

Derived* d = new Derived();
Base* b = static_cast<Base*>(d); // ✅ 安全

1.2.3 空指针转换

void* p = nullptr;
int* q = static_cast<int*>(p);

1.2.4 显式调用单参数构造函数 / 转换函数

string s = static_cast<string>("hello");

1.2.5 把表达式转为右值(配合移动语义)

int a = 10;
int&& b = static_cast<int&&>(a);

1.3 不能做什么(绝对不行)

1.3.1 不能用于 向下转型(不安全)

基类 → 派生类,static_cast 不检查是否真的是该对象

Base* b = new Base();
Derived* d = static_cast<Derived*>(b); // ❌ 编译过,但运行会炸

👉 向下转型必须用 dynamic_cast

1.3.2 不能去掉 const

const int a = 10;
int* p = static_cast<int*>(&a); // ❌ 编译错误

👉 去 const 必须用 const_cast

1.3.3 无关类型之间强转

int* p = static_cast<int*>(100); // ❌ 错误

👉 这种底层强转要用 reinterpret_cast

1.4 核心特点(必须记住)

  1. 编译期转换,没有运行时开销
  2. 只允许合法、有意义的转换
  3. 向上转型(派生→基类)非常安全
  4. 比 C 风格强转 (type) 更安全、更清晰
  5. 不能做动态检查、不能去 const、不能乱转指针

1.5 和其他转换的区别(超级好记)

转换 用途
static_cast 正常、安全、编译期转换
dynamic_cast 继承类向下转型(运行时检查)
const_cast 去掉 / 添加 const
reinterpret_cast 底层二进制强转(危险)

1.6 最简单记忆口诀

  • static_cast 最安全,
  • 基本类型继承转
  • 不能去 const 不能乱转
  • 向下转型别用它

2.动态转换(dynamic_cast)

2.1 基本作用

dynamic_cast 是 C++ 专门用于多态类型转换的运算符,主要做:

  • 基类指针 / 引用 → 派生类指针 / 引用(向下转型)
  • 也可以做横向转换(同一继承树内的兄弟类)

它是唯一一个在运行时做检查的类型转换。

2.2 核心前提(必须满足)

要使用 dynamic_cast,基类必须包含至少一个虚函数(要有虚表、支持多态),否则编译报错。

2.3 两种用法 & 结果

2.3.1 指针转换

Base* base_ptr = new Derived();

// 尝试转成 Derived*
Derived* der_ptr = dynamic_cast<Derived*>(base_ptr);
  • 转换成功:返回有效指针
  • 转换失败:返回 nullptr

2.3.2 引用转换

Base& base_ref = derived_obj;
Derived& der_ref = dynamic_cast<Derived&>(base_ref);
  • 成功:返回派生类引用
  • 失败:抛出 std::bad_cast 异常

引用没有 “空引用”,所以失败只能抛异常。

2.4 安全 vs 不安全

  • static_cast 向下转型:

    不检查,直接强转,错了也不知道 → 不安全

  • dynamic_cast 向下转型:

    运行时查真实类型 → 安全

2.5 适用场景

  • 你拿到一个基类指针 / 引用,但不确定它实际指向哪个子类
  • 需要调用只有子类才有的成员函数
  • 框架、插件、多态对象管理中大量使用

2.6 典型示例

class Base {
public:
    virtual ~Base() {}  // 必须有虚函数
};

class Derived : public Base {};

int main() {
    Base* b = new Derived;

    Derived* d = dynamic_cast<Derived*>(b);

    if (d) {
        // 转换成功
    } else {
        // 不是 Derived 类型
    }
}

2.7 一句话总结

  • dynamic_cast = 运行时安全向下转型
  • 必须有多态(虚函数)
  • 指针失败返回 nullptr,引用失败抛异常

3.常量转换(const_cast)

3.1 作用只有一个

用于增加或去除指针 / 引用上的 const、volatile 限定

不能改变类型,只能改 “常量性”。

3.2 只能用于

  • 指针
  • 引用
  • 指向对象的成员指针

不能用于普通变量。

3.3 最常见用法:去掉 const

const int a = 10;
const int* p = &a;

// 去掉 const
int* q = const_cast<int*>(p);
void func(const int& x) {
    // 内部需要修改时
    int& m = const_cast<int&>(x);
}

3.4 也可以增加 const

int x = 10;
int* p = &x;

const int* q = const_cast<const int*>(p);

3.5 重要危险规则

  • const_cast 本身是安全的
  • 修改原本就是 const 的对象是未定义行为
const int a = 10;
int* p = const_cast<int*>(&a);
*p = 20; // ❌ 未定义行为!可能崩溃、可能不变

只有原本不是 const 的对象,去掉 const 再修改才安全:

int x = 10;
const int* pc = &x;
int* p = const_cast<int*>(pc);
*p = 20; // ✅ 安全

3.6 一句话记忆

const_cast 只改常量性,不改类型;

能加能去 const,只对指针引用;

改真 const 对象 = 未定义行为。

4.重新解释转换(reinterpret_cast)

reinterpret_cast = 重新解释二进制内存

它不做任何计算、不检查、不转换值,只把一段内存强行当成另一种类型看

4.1 一句话核心

  • 最暴力、最危险、最接近 C 语言强转 (type)
  • 只改变编译器怎么看待这段内存,不改变内存本身
  • 用于底层、系统、硬件、网络、指针地址操作

4.2 典型用法

① 无关指针类型互转

int a = 0x12345678;
int* p = &a;

// 把 int* 强行看成 char*
char* c = reinterpret_cast<char*>(p);

② 指针 ↔ 整数互转(地址操作)

int x = 10;
// 指针 → 整数(地址值)
uint64_t addr = reinterpret_cast<uint64_t>(&x);

// 整数 → 指针
int* q = reinterpret_cast<int*>(addr);

③ 函数指针强转

void (*fp)() = nullptr;
// 强行看成另一种函数指针
using Func = int(*)(int);
Func f = reinterpret_cast<Func>(fp);

4.3 特点(必须记住)

  1. 编译期完成,无运行时开销
  2. 几乎不做安全检查,转错就炸
  3. 不修改二进制数据,只改 “解释方式”
  4. 不可用于:
    • 直接转普通数值(如 int→double)
    • 去掉 const(必须用 const_cast)

4.4 适用场景(正经用途)

  • 操作系统、驱动、嵌入式开发
  • 网络协议解析(字节流转结构体)
  • 内存布局操作、hook、注入
  • 与 C 接口、硬件寄存器交互

日常业务代码几乎不应该用

4.5 一句话记忆

reinterpret_cast 不转值,只改内存解释;

指针随便转,地址转整数;

高效但危险,只用于底层。

posted @ 2023-07-11 15:08  CodeMagicianT  阅读(280)  评论(0)    收藏  举报