C++ 类型转换与 IO 流
概述
在 C++ 编程体系中,类型转换与 IO 流是支撑程序数据处理与交互的两大核心环节。类型转换关乎数据在不同类型间的安全传递与运算适配,而 IO 流则负责程序与外部设备(如键盘、屏幕、文件)之间的数据输入与输出。
C 语言中的类型转换方式虽简洁,却存在可视性差、难以追踪的问题,容易在复杂程序中引发潜在的逻辑错误。为解决这一痛点,C++ 引入了四种命名明确的强制类型转换操作符,通过规范的语法形式,让类型转换过程更清晰、更可控。
而在 IO 流领域,C++ 在兼容 C 语言 IO 函数的基础上,构建了更具面向对象特性的 IO 流体系。从用于控制台交互的 istream、ostream,到用于文件操作的 ifstream、ofstream 与 fstream,再到用于字符串数据处理的 stringstream,C++ 的 IO 流机制为不同场景下的数据传输提供了灵活、统一的接口。
C++ 的类型转换
四种命名的强制类型转换操作符
static_cast
static_cast 用于非多态类型的转换(静态转换)。编译器隐式执行的任何类型转换都可用,但通常不推荐用于两个不相关的类型进行转换。
示例:
int a = 10;
double b = static_cast<double>(a);
reinterpret_cast
reinterpret_cast 用于不同类型之间的底层位模式重解释转换。它不进行安全检查,仅重新解释指针或引用的二进制表示。
示例:
int n = 10;
void* p = &n;
int* p2 = reinterpret_cast<int*>(p);
const_cast
const_cast 的作用就是删除变量的 const 属性。需要注意的是,在用指针去改变原本 const 对象的值时,如果该对象本身是 const 定义的,修改行为可能导致未定义行为。此时可能需要 volatile 关键字来确保编译器每次都访问内存里的变量。
示例:
const int n = 10;
int* p2 = const_cast<int*>(&n);
// *p2 = 20; // 谨慎使用,可能产生未定义行为
dynamic_cast
dynamic_cast 用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)。
dynamic_cast只能用于父类含有虚函数的类。dynamic_cast会检查是否能转换成功,能成功的话就转换,不能成功的话会返回空指针。
如果是子类转换成父类的话,不需要 dynamic_cast,用 static_cast 就行了。如果是父类转换成子类的话,用 dynamic_cast——这是安全的,但不一定能转换成功。
RTTI (运行时类型识别)
RTTI (Run-Time Type Information) 允许在运行时识别对象的实际类型。C++ 支持 RTTI 的方式主要有:
typeid运算符dynamic_cast运算符decltype(主要用于编译期推导,但在某些上下文中辅助类型识别)
C++ 的 IO 流
C++ IO 流主要包含以下类:
istream:输入流ostream:输出流iostream:输入输出流
C 语言的 IO 函数(如 fprintf, fscanf, printf, scanf)在 C++ 中依然可用,但对于自定义类型,推荐使用 cin 和 cout 以支持重载操作符。
提示: 如果程序一直要求输入,可以使用 Ctrl+Z 终止输入(Windows),当然 Ctrl+C 也可以。
ios 流里面有个 operator bool() 的成员函数来判断输入输出流的状态。
C++ 文件的 IO 流
C 语言文件的 IO 流同样可以使用,但 C++ 提供了更面向对象的封装:
- ifstream:专门用于从文件中读取数据。
- ofstream:专门用于向文件中写入数据。
- fstream:结合了
ifstream和ofstream的功能,允许对同一个文件进行读写操作。
示例:
#include <fstream>
#include <iostream>
struct Info {
int id;
char name[20];
};
int main() {
// 打开文件,二进制模式读取
std::ifstream ifs("text.txt", std::ios_base::in | std::ios_base::binary);
Info info;
if (ifs.read((char*)&info, sizeof(info))) {
// 处理读取的数据
}
// 文本模式读取
ifs.clear();
ifs.seekg(0);
ifs >> info.id;
return 0;
}
注意: 二进制读写不能用 string、vector 这样的对象直接存数据,因为这样写进去的只会是一个指针,如果进程结束了就成野指针了。应使用固定大小的缓冲区或序列化格式。
stringstream
stringstream 用于将字符串作为流进行读写操作,常用于数据格式转换。
用途:
- 数据转换成字符串
- 序列化和反序列化结构数据
示例:
#include <sstream>
#include <string>
int main() {
std::stringstream ss;
int num = 123;
ss << num; // 整数转字符串
std::string str = ss.str();
ss.clear();
ss << str;
int back = 0;
ss >> back; // 字符串转整数
return 0;
}
虽然 stringstream 可用于序列化,但在生产环境中处理复杂数据结构时,一般建议使用专门的序列化库。

