张三的易容术:C++ 四大类型转换
第一回:最规矩的易容术 static_cast (静态转换)
这把刀是张三平时用得最多的,它主打一个**"讲道理、守规矩"**。它能在编译阶段(写代码的时候)就帮你把类型转好。
适用场景:
-
基础数据类型互转 :把
int转成double。 -
有血缘关系的类 :子类指针转成父类指针(向上转型,绝对安全);或者父类指针转成子类指针(向下转型,但编译器不帮你检查,转错了算你倒霉)。
-
干点小杂活 :把
void*(无类型指针)转回具体的类型。
cpp
double pi = 3.14;
int i = static_cast<int>(pi); // 3.14 变成了 3,讲道理,没毛病
class Animal {};
class Dog : public Animal {};
Dog* dog = new Dog();
Animal* animal = static_cast<Animal*>(dog); // ✅ 子类转父类,天经地义
张三心法 :static_cast 在编译时就检查了,没有运行时的额外开销,速度极快。
第二回:鉴宝大师的试金石 dynamic_cast (动态转换)
这把刀极其特殊,它是专门用来处理**"家族血统"** (类的继承)的。它主打一个**"安全第一"**。
假设你手里拿着一个 Animal 的指针,你想把它转成 Dog 的指针。但你不知道它到底是不是狗,万一是只猫呢?此时如果你用 static_cast,强转成狗去调用"汪汪叫"的方法,程序立马崩溃。
用 dynamic_cast,它会在这个指针身上摸一摸,查一下底细:
-
如果它真的是狗,转换成功,返回指针。
-
如果它是只猫,转换失败,安全地返回
nullptr(空指针),绝不崩溃!
cpp
Animal* animal = new Animal();
// 如果是 strong 转,程序就崩了
// Dog* dog = static_cast<Dog*>(animal); ❌ 危险!
// 用 dynamic_cast,安全探底
Dog* dog = dynamic_cast<Dog*>(animal);
if (dog) {
// 真的是狗,可以汪汪叫
} else {
// 是空的,说明它不是狗,张三捡回一条命
}
张三心法 :dynamic_cast 依赖运行时的检查(RTTI),速度比较慢。只有在必须进行安全的向下转型时才用它。而且,它只能用于带有虚函数的类。
第三回:突破封印的刺客 const_cast (常量转换)
前面咱们讲过,用 const 封印的变量,是绝对不准修改的。但有时候,张三拿到了一份老代码,对方传给张三的变量带了 const,可张三底层的接口偏偏要求接收一个非 const 的指针。
这时候,张三需要一把专门"撕毁封印"的匕首:const_cast。它能去掉变量身上的 const 或 volatile 属性。
cpp
void oldFunction(int* p) { *p = 100; } // 老接口非要非 const 的指针
void zhangSan(const int* p) {
// 撕毁 const 封印
int* mutable_p = const_cast<int*>(p);
oldFunction(mutable_p);
}
⚠️ 终极警告 :这把匕首极度危险!如果这个变量本身 在内存里就是被 const 锁死的(比如存在只读内存区),你用 const_cast 撕毁封印去强改,程序当场走火入魔(段错误崩溃)。它只适合用在那些"原本不是 const,只是传参时被误加了 const"的情况。
第四回:指鹿为马的魔教神功 reinterpret_cast (重新解释转换)
这把刀根本不管什么道理,也不管什么家族血统。它主打一个**"指鹿为马"**。
它直接把这串内存里的二进制 01 序列,强行当成了另外一种东西。你在看底层代码、网络协议、硬件驱动时经常见到它。
cpp
int a = 65;
// 把 a 的地址(指针),强行解释成一个字符指针
char* p = reinterpret_cast<char*>(&a);
// 此时 *p 就是 'A',因为我们把整数的内存强行当字符看了
张三心法:这是最暴力的转换,编译器完全不检查,极度不安全,非底层开发(比如用 MapLibre 去看显卡内存)绝对不要用。
大结局:张三的四大易容刀
| 转换刀法 | 用途 | 危险指数 | 什么时候用? |
|---|---|---|---|
static_cast |
普通转换、数值转换 | ⭐ | 日常开发 95% 的场景用它。 |
dynamic_cast |
安全的向下转型 | ⭐⭐ | 不确定父类指针指向哪个子类时用它。 |
const_cast |
去除 const 属性 |
⭐⭐⭐ | 被迫向老旧接口妥协时用它。 |
reinterpret_cast |
内存二进制重新解释 | ⭐⭐⭐⭐⭐ | 底层、驱动、极度硬核的场景。 |