cpp拾遗——流
0. cpp 对 带缓存的输入输出的改进
c printf scanf 的缺点:
- 无法检查类型,如 print("%s", a); a可以是 int 类型,也能编译通过。
- 无法扩展,如 希望 自定义一个 %v 输出某个结构体类型。
cpp的流系统解决了如上问题
cpp的流系统如下
常用头文件,和提供的功能
- iostream 包含了对输入输出流进行操作所需的基本信息。
- fstream 用于用户管理的文件的I/O操作。
- strstream 用于字符串流I/O。
- stdiostream 用于混合使用C和C + +的I/O机制时,例如想将C程序转变为C++程序。
- iomanip 在使用格式化I/O时应包含此头文件。
缓存IO
和c标准库一样,不过cpp的更方便,不仅输出缓存,输入也缓存,所以可以提供很多操作
cout,遇到 endl时,输出到标准输出
cerr,输出到标准错误,无缓存
clog,输出到标准错误,有缓存
1. 流对象分析
打开 iostream,知道预先定义了 多个流对象
60 extern istream cin; /// Linked to standard input
61 extern ostream cout; /// Linked to standard output
62 extern ostream cerr; /// Linked to standard error (unbuffered)
63 extern ostream clog; /// Linked to standard error (buffered)
搜索 ostream 定义,发现其为 basic_ostream
137 /// Base class for @c char input streams.
138 typedef basic_istream<char> istream;
139
140 /// Base class for @c char output streams.
141 typedef basic_ostream<char> ostream;
打开 ostream ,知道 basic_ostream的定义
57 template<typename _CharT, typename _Traits>
58 class basic_ostream : virtual public basic_ios<_CharT, _Traits>
basic_ostream的声明有点怪,有点像声明了 basic_ostream 两次,但其实是这样的
// basic_ostream 继承 basic_ios,
// 由于 basic_ios 是模板类,所以 basic_ostream也是模板类,
// 在 basic_ostream 内声明 类 sentry
template<typename _CharT, typename _Traits>
class basic_ostream : virtual public basic_ios<_CharT, _Traits>
{
class sentry;
friend class sentry;
};
// 完成 sentry 的声明
// basic_ostream<_CharT, _Traits> :具体化一种 basic_ostream类,毕竟只有模板类具体化后才能使用内部成员
template <typename _CharT, typename _Traits>
class basic_ostream<_CharT, _Traits>::sentry
{
};
说明下类中声明类
class A{
public:
class B;
};
class A::B {
public:
int a;
};
class B{
public:
int a;
};
int main()
{
B a;
a.a = 1;
A::B a2;
a2.a = 2;
return 0;
}
类有namespace的效果,所以根据namespace的本质,类中声明类,翻译为c语言为
struct A_B {
int a;
};
struct B {
int a;
};
继续分析basic_ostream,可以发现 类模板更好的风格,是用 typedef 对形参类型 进行重命名
60 public:
61 // Types (inherited from basic_ios):
62 typedef _CharT char_type;
66 typedef _Traits traits_type;
basic_ostream 主要实现流操作<<
其父类 basic_ios 实现缓存。
其父类 ios_base 定义很多 flag。