C++四种类型转换面试必考:static_cast、dynamic_cast、const_cast、reinterpret_cast全解析,90%的候选人说不清楚!
面试官:C++有哪几种类型转换?你:static_cast、dynamic_cast、const_cast、reinterpret_cast。面试官:它们各自的使用场景是什么?dynamic_cast的底层原理是什么?什么情况下用reinterpret_cast?你:……
前言
C++类型转换是面试中的必考知识点,几乎每一场C++技术面试都会问到。
很多人只知道"强制类型转换"用括号(Type)value,但面试官一追问就露馅了:
static_cast和dynamic_cast到底有什么区别?const_cast真的能去掉 const 吗?去掉之后修改会怎样?reinterpret_cast为什么被称为"恶魔的转换"?- 为什么C++要引入这四种转换,C风格的
(Type)有什么不好?
这篇文章,我把这四种类型转换从底层原理到实战用法再到面试高频问答全部讲透。看完之后,面试官问到类型转换,你可以侃侃而谈五分钟不带停的。
一、为什么C++要引入四种类型转换?
在C语言中,类型转换非常简单粗暴:
inta=10;floatb=(float)a;// C风格强制转换constchar*p="hello";char*q=(char*)p;// 去掉const,C语言不管这些C风格的问题在于:它不区分安全的转换和不安全的转换。所有转换都长一个样,编译器无法帮你检查意图,代码审查的人也看不出你到底想干什么。
C++引入了四种关键字级别的类型转换,每种都有明确的语义:
| 关键字 | 用途 | 安全性 |
|---|---|---|
static_cast | 编译期可检查的类型转换 | 较安全 |
dynamic_cast | 运行时安全的向下转换 | 最安全 |
const_cast | 去掉或添加 const/volatile | 特定场景 |
reinterpret_cast | 低级别的位模式重新解释 | 最危险 |
面试回答模板:C++引入四种类型转换是为了让转换意图明确、可检查、可搜索。C风格转换不区分安全性,编译器无法给出有意义的警告,代码审查也无法快速定位潜在问题。
二、static_cast:编译期的"常规转换"
2.1 基本用法
static_cast是最常用的类型转换,用于编译期可以确定安全性的转换:
#include<iostream>intmain(){// 1. 基本类型转换inta=65;floatf=static_cast<float>(a);// int -> float,安全doubled=static_cast<double>(a);// int -> double,安全// 2. 指针/引用向上转换(子类 -> 父类)structBase{virtualvoidfoo(){}};structDerived:Base{};Derived d_obj;Base*bp=static_cast<Base*>(&d_obj);// 向上转换,安全// 3. 枚举和整数之间转换enumColor{RED,GREEN,BLUE};intc=static_cast<int>(RED);// 枚举 -> int,安全Color color=static_cast<Color>(1);// int -> 枚举,可以但不推荐// 4. void* 和其他指针之间转换intx=42;void*vp=static_cast<void*>(&x);// int* -> void*,安全int*ip=static_cast<int*>(vp);// void* -> int*,程序员保证类型正确return0;}2.2 关键特性
- 编译期检查:不合法的转换会在编译时报错
- 不做运行时检查:如果转换实际上不安全(比如 void* 转错了类型),编译器不会拦你
- 不产生运行时开销:和C风格转换一样高效
2.3 典型使用场景
// 场景1:整数除法要得到浮点结果inta=7,b=2;floatresult=static_cast<float>(a)/b;// 3.5 而不是 3// 场景2:从 void* 恢复类型(常见于回调函数)voidcallback(void*data){MyStruct*obj=static_cast<MyStruct*>(data);// 程序员保证data确实是MyStruct*obj->doSomething();}// 场景3:隐式转换的显式化(消除编译器警告)voidprocess(size_t size);intn=100;process(static_cast<size_t>(n));// 明确告诉编译器:我知道这里有转换三、dynamic_cast:运行时安全的"向下转换"
3.1 基本用法
dynamic_cast是四种转换中唯一在运行时进行类型检查的。它专门用于继承体系中的向下转换(父类指针转子类指针):
#include<iostream>#include<string>classAnimal{public:virtual~Animal()=default;// 必须有虚函数!virtualvoidspeak()const{std::cout<<"...\n";}};classDog:publicAnimal{public:voidspeak()constoverride{std::cout<<"Woof!\n";}voidfetch()const{std::cout<<"Fetching!\n";}};classCat:publicAnimal{public:voidspeak()constoverride{std::cout<<"Meow!\n";}voidpurr()const{std::cout<<"Purring...\n";}};voidinteract(Animal*animal){// animal->fetch(); // 编译错误!Animal没有fetch方法// 尝试向下转换为Dog*Dog*dog=dynamic_cast<Dog*>(animal);if(dog){dog->fetch(