C++ Stream 类层次结构深度解析 ios_base basic_ios basic_streambuf basic_ostream basic_istream basic_iostream
C++ Stream 类层次结构解析摘要 C++ I/O流类层次结构从底层到高层依次为:ios_base、basic_ios、basic_streambuf及其派生类。 ios_base:提供流的基础设施,包括: 格式化标志管理(hex/dec/oct等格式) 异常处理机制(goodbit/eofbit等状态) 本地化支持(如数字分隔符) 扩展存储功能 basic_ios:管理流状态和缓冲区,核心
C++ Stream 类层次结构深度解析
文章目录
下面我将对 C++ I/O 流类层次结构进行更加深入和详细的解析,包括每个类的设计目的、关键成员函数、使用场景以及更完整的代码示例。
1. ios_base
- 流的基础设施
ios_base
是所有流类的根基,不依赖于字符类型或流缓冲区,提供流的基础设施。
核心功能
-
格式化标志管理
-
fmtflags
类型定义:hex
,dec
,oct
,left
,right
,scientific
,fixed
等 -
setf()
,unsetf()
,flags()
操作标志
-
-
异常处理
-
iostate
类型定义:goodbit
,eofbit
,failbit
,badbit
-
exceptions()
设置异常掩码
-
-
本地化
imbue()
设置本地化环境
-
扩展存储
xalloc()
,iword()
,pword()
提供用户自定义存储
详细示例
#include <iostream>
#include <locale>
void formatFlagsDemo() {
// 保存当前标志
std::ios_base::fmtflags old_flags = std::cout.flags();
// 设置十六进制输出,显示基数前缀,宽度10,左对齐
std::cout.setf(std::ios_base::hex | std::ios_base::showbase | std::ios_base::left,
std::ios_base::basefield | std::ios_base::adjustfield);
std::cout.width(10);
std::cout << 255 << std::endl; // 输出 "0xff "
// 恢复标志
std::cout.flags(old_flags);
}
void exceptionHandlingDemo() {
std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
try {
int value;
std::cout << "Enter an integer: ";
std::cin >> value; // 输入非数字会触发异常
} catch (const std::ios_base::failure& e) {
std::cerr << "I/O error: " << e.what() << '\n';
if (std::cin.rdstate() & std::ios_base::failbit) {
std::cin.clear(); // 清除错误状态
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
}
void localizationDemo() {
// 使用德国本地化环境,数字中使用逗号作为小数点
std::cout.imbue(std::locale("de_DE"));
std::cout << 1234.56 << std::endl; // 输出 "1.234,56"
// 恢复默认本地化
std::cout.imbue(std::locale());
}
int main() {
formatFlagsDemo();
exceptionHandlingDemo();
localizationDemo();
return 0;
}
2. basic_ios
- 流的核心管理
basic_ios
是类模板,管理流的状态和缓冲区,是 basic_istream
和 basic_ostream
的直接基类。
核心功能
-
流状态管理
-
rdstate()
,setstate()
,clear()
-
good()
,eof()
,fail()
,bad()
-
-
缓冲区管理
rdbuf()
,rdbuf(streambuf*)
-
格式化上下文
copyfmt()
复制格式化设置
-
填充字符
fill()
,fill(char)
详细示例
#include <iostream>
#include <fstream>
#include <sstream>
void streamStateDemo() {
std::ifstream file("nonexistent.txt");
// 检查流状态
if (file.fail()) {
std::cout << "File open failed. State: ";
if (file.rdstate() & std::ios_base::badbit)
std::cout << "badbit ";
if (file.rdstate() & std::ios_base::failbit)
std::cout << "failbit ";
if (file.rdstate() & std::ios_base::eofbit)
std::cout << "eofbit ";
std::cout << '\n';
}
}
void bufferManagementDemo() {
std::filebuf fb;
if (fb.open("test.txt", std::ios::out)) {
std::ostream os(&fb);
os << "Writing to file via streambuf\n";
fb.close();
}
// 重定向 cout
std::streambuf* old_buf = std::cout.rdbuf();
std::ofstream file("cout_redirect.txt");
std::cout.rdbuf(file.rdbuf());
std::cout << "This goes to file\n";
std::cout.rdbuf(old_buf);
file.close();
}
void formatCopyDemo() {
std::ostream os(nullptr); // 无缓冲区
// 从 cout 复制格式化设置
os.copyfmt(std::cout);
os.clear(std::cout.rdstate());
// 设置新的缓冲区
std::stringbuf sb;
os.rdbuf(&sb);
os << "Formatted like cout: " << std::hex << 255;
std::cout << "Captured output: " << sb.str() << '\n';
}
int main() {
streamStateDemo();
bufferManagementDemo();
formatCopyDemo();
return 0;
}
3. basic_streambuf
- 底层缓冲区抽象
basic_streambuf
是流的核心,负责实际的 I/O 操作。
核心功能
-
缓冲区管理
-
pubsetbuf()
,pubseekoff()
,pubseekpos()
-
in_avail()
,snextc()
,sbumpc()
,sgetc()
-
-
输入区域
underflow()
,uflow()
,showmanyc()
-
输出区域
overflow()
,xsputn()
,sync()
-
放置区域
pbackfail()
详细示例:自定义缓冲区
#include <iostream>
#include <streambuf>
#include <cstdio>
class TeeBuffer : public std::streambuf {
private:
std::streambuf* src;
std::ostream& copy;
char buffer;
protected:
int_type underflow() override {
int_type ch = src->sbumpc();
if (ch != traits_type::eof()) {
buffer = ch;
copy.put(ch);
setg(&buffer, &buffer, &buffer + 1);
}
return ch;
}
public:
TeeBuffer(std::streambuf* src, std::ostream& copy)
: src(src), copy(copy) {}
};
class TeeStream : public std::istream {
private:
TeeBuffer tb;
public:
TeeStream(std::istream& in, std::ostream& copy)
: std::istream(&tb), tb(in.rdbuf(), copy) {}
};
int main() {
// 将 cin 同时输出到 cout
TeeStream tee(std::cin, std::cout);
std::cout << "Type something (will echo): ";
std::string input;
tee >> input;
std::cout << "\nYou typed: " << input << '\n';
return 0;
}
4. basic_ostream
- 高级输出接口
核心功能
-
插入操作
operator<<
重载
-
定位
tellp()
,seekp()
-
刷新
flush()
,put()
,write()
详细示例
#include <iostream>
#include <fstream>
#include <iomanip>
#include <bitset>
void outputOperations() {
// 基本输出
std::cout << "Standard output\n";
// 无缓冲输出
std::cerr << "Error message\n";
// 格式化输出
std::cout << std::boolalpha << true << ' ' << false << '\n';
std::cout << std::hex << std::showbase << 255 << '\n';
std::cout << std::scientific << 123.456 << '\n';
// 原始输出
const char* data = "Raw data";
std::cout.write(data, 8).put('\n');
// 二进制输出
std::bitset<8> bits(0xAA);
std::cout << bits << '\n';
}
void filePositioning() {
std::fstream file("position.txt", std::ios::out | std::ios::in | std::ios::trunc);
file << "Hello World";
// 获取当前位置
std::streampos pos = file.tellp();
std::cout << "Current position: " << pos << '\n';
// 移动到开头
file.seekp(0, std::ios::beg);
file << "HELLO";
// 移动到末尾
file.seekp(0, std::ios::end);
file << "!!!";
file.close();
}
int main() {
outputOperations();
filePositioning();
return 0;
}
5. basic_istream
- 高级输入接口
核心功能
-
提取操作
operator>>
重载
-
无格式输入
get()
,getline()
,read()
,readsome()
-
定位
tellg()
,seekg()
-
忽略
ignore()
详细示例
#include <iostream>
#include <fstream>
#include <limits>
#include <iomanip>
void inputOperations() {
// 基本输入
int i;
std::cout << "Enter an integer: ";
std::cin >> i;
// 处理错误
if (std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "Invalid input\n";
} else {
std::cout << "You entered: " << i << '\n';
}
// 行输入
std::cout << "Enter a line: ";
std::string line;
std::cin.ignore(); // 清除之前的换行符
std::getline(std::cin, line);
std::cout << "Line: " << line << '\n';
// 原始输入
char buffer[10];
std::cout << "Enter 5 characters: ";
std::cin.read(buffer, 5);
buffer[5] = '\0';
std::cout << "Read: " << buffer << '\n';
}
void binaryFileReading() {
std::ifstream file("data.bin", std::ios::binary);
if (file) {
// 获取文件大小
file.seekg(0, std::ios::end);
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
// 读取整个文件
char* buffer = new char[size];
file.read(buffer, size);
// 处理二进制数据...
delete[] buffer;
}
}
int main() {
inputOperations();
binaryFileReading();
return 0;
}
6. basic_iostream
- 双向流
核心功能
-
同时继承
basic_istream
和basic_ostream
-
用于需要同时进行输入输出的场景
-
常用于字符串流和文件流
详细示例
#include <iostream>
#include <sstream>
#include <string>
void stringStreamDemo() {
std::stringstream ss;
// 写入
ss << "Number: " << 42 << " Pi: " << 3.14159;
// 读取
std::string token;
while (ss >> token) {
std::cout << "Token: " << token << '\n';
}
// 重置流
ss.clear();
ss.str(""); // 清空内容
// 重新使用
ss << "New content";
std::cout << ss.str() << '\n';
}
void fileStreamDemo() {
std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::trunc);
if (file) {
// 写入
file << "Line 1\nLine 2\nLine 3\n";
// 回到开头读取
file.seekg(0);
std::string line;
while (std::getline(file, line)) {
std::cout << "Read: " << line << '\n';
}
// 追加内容
file.clear(); // 清除EOF标志
file.seekp(0, std::ios::end);
file << "Line 4\n";
file.close();
}
}
int main() {
stringStreamDemo();
fileStreamDemo();
return 0;
}
总结
C++ 的流类层次结构提供了强大而灵活的 I/O 系统:
-
分层设计:从底层的
basic_streambuf
到高层的basic_istream
/basic_ostream
-
可扩展性:可以通过派生自定义缓冲区或重载操作符来扩展功能
-
统一接口:对控制台、文件、内存等不同设备提供一致的接口
-
国际化支持:通过本地化支持多语言环境
-
类型安全:类型安全的 I/O 操作
理解这些类的层次结构和相互关系对于开发高级 I/O 功能至关重要,特别是在需要自定义流行为或实现特殊 I/O 设备支持时。
更多推荐
所有评论(0)