A. 隐式标准转换(Standard Conversion Sequence)
- 整型提升
cpp
char c = 'A';
int i = c; // char → int 提升,无警告
std::cout << i; // 65
- 整型 ↔ 浮点
cpp
double d = 3; // int → double
int n = 3.14; // double → int,截断为 3
- 数组退化(array-to-pointer)
cpp
int a[4] = {1,2,3,4};
int* p = a; // 数组名退化为 int*
- 指针转换
cpp
int x = 0;
int* p = &x;
void* pv = p; // int* → void* 隐式
一句话规则:无需写任何关键字,编译器自动完成;只在"安全"场景下出现。
B. 用户定义转换(User-Defined Conversion)
- 转换构造函数
cpp
struct Length {
double m;
Length(double x) : m(x) {} // 转换构造
};
Length L = 42.0; // double → Length,隐式
- 转换函数
cpp
struct Money {
double amount;
explicit operator double() const { return amount; }
};
Money m{100};
double d = static_cast<double>(m); // 必须显式
一句话规则:把"别的类型→本类型"写成构造函数;把"本类型→别的类型"写成 operator T()
。
坑点:explicit
能堵住隐式,但挡不住显式 cast。
C. 继承体系里的三种 cast
- 向上转型(Up-cast)
cpp
struct Base { virtual ~Base() = default; };
struct Derived : Base {};
Derived d;
Base* pb = &d; // 隐式安全
- 向下转型(Down-cast)
cpp
Base* pb = new Derived;
Derived* pd = dynamic_cast<Derived*>(pb); // 安全,失败返回 nullptr
- 交叉转型(Cross-cast)
cpp
struct A { virtual ~A() = default; };
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
D obj;
B* pb = &obj;
C* pc = dynamic_cast<C*>(pb); // B→C,成功
一句话规则:
- 向上永远安全;
- 向下/交叉用
dynamic_cast
,否则 UB。
D. 对象切片(Slicing)
cpp
struct Person { std::string name = "base"; };
struct Student : Person { int id = 42; };
Student s;
Person p = s; // 只拷贝 Person 部分,id 丢失
std::cout << p.name; // base
一句话规则:把派生类对象 按值赋给/传参给 基类就会切片,改为指针/引用可避免。
E. 四种显式 cast
- static_cast(编译期检查)
cpp
int i = 10;
double d = static_cast<double>(i);
- dynamic_cast(运行期 RTTI)
cpp
Base* pb = new Derived;
Derived* pd = dynamic_cast<Derived*>(pb);
- const_cast(仅改 cv 限定)
cpp
const int ci = 5;
int* modifiable = const_cast<int*>(&ci); // 注意:改值 UB
- reinterpret_cast(位级重解释)
cpp
int n = 0x1234;
int* p = &n;
std::uintptr_t v = reinterpret_cast<std::uintptr_t>(p);
一句话规则:
- 数值/枚举/指针用
static_cast
; - 跨继承用
dynamic_cast
; - 去 const 用
const_cast
; - 位级解释用
reinterpret_cast
。
F. 模板与转换(enable_if / concepts)
cpp
template<class T>
auto abs_val(T v)
-> std::enable_if_t<std::is_signed_v<T>, T>
{
return v < 0 ? -v : v;
}
C++20 Concepts 写法:
cpp
template<std::signed_integral T>
T abs_val(T v) { return v < 0 ? -v : v; }
一句话规则:用 type traits 或 concepts 在编译期把"能否转换"写成约束。
G. C++20 bit_cast
cpp
float f = 3.14f;
uint32_t u = std::bit_cast<uint32_t>(f); // 与 memcpy 等效,安全
一句话规则:把 TriviallyCopyable 类型的位模式按字节搬到另一个同样大小的类型,零开销、无 UB。
使用速查表
需求 | 推荐 | 禁止 |
---|---|---|
数值互转 | static_cast | C-style |
派生→基类 | 隐式或 static_cast | --- |
基类→派生 | dynamic_cast | static_cast(可能 UB) |
去掉 const | const_cast | reinterpret_cast |
位级重解释 | bit_cast / reinterpret_cast | C-style |
模板约束 | enable_if / concepts | --- |
把示例直接拷进小文件即可独立编译运行。