C++类型转换 #
一、类型转换概述 #
类型转换是将一种数据类型的值转换为另一种数据类型的过程。C++支持两种类型转换:
- 隐式类型转换:编译器自动进行
- 显式类型转换:程序员明确指定
二、隐式类型转换 #
2.1 算术转换 #
cpp
// 整型提升
short s = 10;
int i = s; // short → int
// 浮点提升
float f = 3.14f;
double d = f; // float → double
// 混合运算时的转换
int a = 10;
double b = 3.14;
auto result = a + b; // int → double,result是double
2.2 转换规则 #
cpp
// 转换方向:小类型 → 大类型
// char → short → int → long → long long → float → double → long double
// 混合运算示例
char c = 'A';
short s = 100;
int i = 1000;
long l = 10000;
float f = 3.14f;
double d = 3.14159;
auto r1 = c + s; // int
auto r2 = i + l; // long
auto r3 = f + d; // double
auto r4 = i + f; // float
2.3 赋值转换 #
cpp
int i = 10;
double d = i; // int → double(安全)
double d2 = 3.14;
int i2 = d2; // double → int(可能丢失精度,i2 = 3)
// 无符号转换
int neg = -1;
unsigned int pos = neg; // 很大的正数(回绕)
2.4 布尔转换 #
cpp
// 非零值为true,零为false
int x = 10;
bool b1 = x; // true
int y = 0;
bool b2 = y; // false
double d = 3.14;
bool b3 = d; // true
// 指针转布尔
int* ptr = nullptr;
bool b4 = ptr; // false
int value = 10;
int* ptr2 = &value;
bool b5 = ptr2; // true
三、C风格类型转换 #
3.1 基本语法 #
cpp
double d = 3.14;
// C风格转换
int i1 = (int)d; // 3
int i2 = int(d); // 3
// 问题:不安全,不推荐使用
3.2 C风格转换的问题 #
cpp
const int x = 10;
int* p = (int*)&x; // 移除const,危险!
class Base {};
class Derived : public Base {};
class Other {};
Base* base = new Derived;
Other* other = (Other*)base; // 完全不相关的类型转换,危险!
四、C++风格类型转换 #
C++提供了四种类型转换运算符,更加安全和明确。
4.1 static_cast #
用于相关类型之间的转换。
cpp
// 基本类型转换
double d = 3.14;
int i = static_cast<int>(d); // 3
// 指针转换(相关类型)
void* ptr = &i;
int* p = static_cast<int*>(ptr);
// 类层次结构中的转换(编译时检查)
class Base { virtual void foo() {} };
class Derived : public Base {};
Base* base = new Derived;
Derived* derived = static_cast<Derived*>(base); // 向下转型
// 不相关类型会编译错误
// int* p1 = static_cast<int*>(&d); // 错误
4.2 dynamic_cast #
用于多态类型的安全向下转型。
cpp
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {
public:
void derivedMethod() { std::cout << "Derived method" << std::endl; }
};
int main() {
Base* base = new Derived;
// 安全的向下转型
Derived* derived = dynamic_cast<Derived*>(base);
if (derived) {
derived->derivedMethod();
}
// 引用转型失败会抛出std::bad_cast异常
try {
Derived& ref = dynamic_cast<Derived&>(*base);
} catch (const std::bad_cast& e) {
std::cout << "Cast failed: " << e.what() << std::endl;
}
delete base;
return 0;
}
4.3 const_cast #
用于移除或添加const属性。
cpp
const int x = 10;
// 移除const
int* p = const_cast<int*>(&x);
*p = 20; // 未定义行为!不要修改原本的const变量
// 合法用途:调用非const版本的函数
void printString(const char* str) {
// 某些旧API可能需要非const参数
char* mutableStr = const_cast<char*>(str);
// 使用mutableStr...
}
// 添加const
int y = 10;
const int* cp = const_cast<const int*>(&y);
4.4 reinterpret_cast #
用于不相关类型之间的低级转换。
cpp
// 指针与整数之间的转换
int x = 10;
long addr = reinterpret_cast<long>(&x);
// 不同指针类型之间的转换
int* pInt = &x;
char* pChar = reinterpret_cast<char*>(pInt);
// 函数指针转换
void (*func1)() = []() {};
int (*func2)() = reinterpret_cast<int(*)()>(func1); // 危险!
// 注意:reinterpret_cast是危险的,慎用
五、类型转换对比 #
5.1 四种cast对比 #
| 转换类型 | 用途 | 安全性 | 运行时检查 |
|---|---|---|---|
| static_cast | 相关类型转换 | 中等 | 无 |
| dynamic_cast | 多态类型向下转型 | 高 | 有 |
| const_cast | 移除/添加const | 低 | 无 |
| reinterpret_cast | 低级位转换 | 很低 | 无 |
5.2 选择指南 #
cpp
// 1. 基本类型转换 → static_cast
double d = 3.14;
int i = static_cast<int>(d);
// 2. 多态向下转型 → dynamic_cast
Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
// 3. 移除const → const_cast(谨慎使用)
const int* cp = &x;
int* p = const_cast<int*>(cp);
// 4. 底层位转换 → reinterpret_cast(尽量避免)
int* pInt = reinterpret_cast<int*>(&d);
六、类型转换函数 #
6.1 标准库转换函数 #
cpp
#include <string>
// 数值转字符串
std::string s1 = std::to_string(123);
std::string s2 = std::to_string(3.14);
// 字符串转数值
int i = std::stoi("123");
long l = std::stol("123456");
double d = std::stod("3.14");
float f = std::stof("3.14f");
6.2 自定义类型转换 #
cpp
class Fraction {
private:
int numerator;
int denominator;
public:
Fraction(int n, int d) : numerator(n), denominator(d) {}
// 转换为double
operator double() const {
return static_cast<double>(numerator) / denominator;
}
// 显式转换函数(C++11)
explicit operator std::string() const {
return std::to_string(numerator) + "/" + std::to_string(denominator);
}
};
int main() {
Fraction f(1, 2);
double d = f; // 隐式转换:0.5
// std::string s = f; // 错误:显式转换函数不能隐式调用
std::string s = static_cast<std::string>(f); // 正确
return 0;
}
七、窄化转换 #
7.1 窄化转换问题 #
cpp
// 窄化转换:大类型 → 小类型,可能丢失数据
double d = 3.14;
int i = d; // 窄化转换,i = 3
long l = 2147483648L;
int i2 = l; // 窄化转换,可能溢出
7.2 使用列表初始化防止窄化转换 #
cpp
double d = 3.14;
// 普通初始化允许窄化转换
int i1 = d; // 警告或无警告
// 列表初始化禁止窄化转换
int i2{d}; // 编译错误!
int i3 = {d}; // 编译错误!
// 正确做法
int i4 = static_cast<int>(d);
int i5{static_cast<int>(d)};
八、类型推导与转换 #
8.1 auto与类型转换 #
cpp
int x = 10;
// auto会丢弃引用和顶层const
const int& ref = x;
auto a = ref; // int(丢弃const和引用)
const auto b = ref; // const int
// auto不会丢弃底层const
const int* ptr = &x;
auto p = ptr; // const int*
8.2 decltype与类型转换 #
cpp
const int x = 10;
// decltype保留所有类型信息
decltype(x) a = 20; // const int
int& ref = x;
decltype(ref) b = x; // int&
九、最佳实践 #
9.1 避免C风格转换 #
cpp
// 不推荐
int i = (int)3.14;
int* p = (int*)malloc(100);
// 推荐
int i = static_cast<int>(3.14);
int* p = static_cast<int*>(malloc(100));
// 或更好的方式
int* p = new int[25];
9.2 优先使用安全转换 #
cpp
class Base { virtual ~Base() {} };
class Derived : public Base {};
Base* base = new Derived;
// 不推荐:不安全的向下转型
Derived* d1 = static_cast<Derived*>(base);
// 推荐:安全的向下转型
Derived* d2 = dynamic_cast<Derived*>(base);
if (d2) {
// 安全使用
}
9.3 使用列表初始化 #
cpp
// 推荐:使用列表初始化防止窄化转换
int x{10};
double d{3.14};
// 需要转换时显式指定
int y{static_cast<int>(d)};
9.4 避免过度使用类型转换 #
cpp
// 类型转换可能表明设计问题
// 尽量使用多态、模板等替代
// 不好的设计
void process(void* data, int type) {
if (type == 1) {
int* p = static_cast<int*>(data);
// ...
} else if (type == 2) {
double* p = static_cast<double*>(data);
// ...
}
}
// 好的设计:使用多态
class Data { virtual void process() = 0; };
class IntData : public Data { void process() override; };
class DoubleData : public Data { void process() override; };
十、总结 #
类型转换一览 #
| 转换方式 | 语法 | 用途 |
|---|---|---|
| 隐式转换 | 自动 | 安全的类型提升 |
| C风格转换 | (Type)value |
不推荐 |
| static_cast | static_cast<Type>(value) |
相关类型转换 |
| dynamic_cast | dynamic_cast<Type>(value) |
多态向下转型 |
| const_cast | const_cast<Type>(value) |
移除const |
| reinterpret_cast | reinterpret_cast<Type>(value) |
低级转换 |
最佳实践 #
- 优先使用C++风格的类型转换
- 使用列表初始化防止窄化转换
- 多态类型使用dynamic_cast
- 避免使用reinterpret_cast
- 设计良好的类型系统,减少类型转换需求
下一步,让我们学习输入输出!
最后更新:2026-03-26