### 前言 我学习C++的时候想要了解深入一点的知识,又由于我C++是零基础,同时C也和零基础差不多,但是个人学习风格习惯,喜欢深入学习,于是从C++ Primer plus 5的一个简单 std::cout << "Hello, World!" << std::endl;** 开始了深入理解。 [源代码地址](https://github.com/StarYuhen/Daily_Practice/blob/master/C%2B%2B/C%2B%2B%20Primer%20plus5ChapterTwo/StdCout.cpp) #### AI阅读文章总结 这篇文章主要讲解了 C++ 中的输出流对象 std::cout 和相关的操作符重载。 首先,文章介绍了 std::cout 对象的原理,以及如何使用 << 插入运算符将字符串插入到输出流中。 其次,文章讲解了 std::endl 的作用,即在输出流中添加一个换行符,以及其源代码中使用的 C++ 模板语法。 接着,文章详细介绍了 << 运算符的重载概念和相关的源代码解释,以及 C++ 中如何使用模板来确定字符类型的特征集。 最后,文章通过自己实现一个输出功能,展示了如何使用命名空间和类来定制自己的输出流。 #### std::cout << "Hello, World!" << std::endl; 解析: 原理: 使用iostream库,同时导入也可以称之为iostream.h 的预处理 包含istream and ostream 两个基类,既输入/输出流 std::cout << "Hello, World!" << std::endl; 这个语句 是因为我们使用了(输出流)cout对象,他在iostream库中,被命名为extern ostream cout;并且设置为导出值 而<<运算符是插入运算符,能将值插入左边的对象,这个语句将"Hello, World!"字符串插入std::cout的输出流对象 而std::endl则是标识一个换行符,模板语法 return flush(__os.put(__os.widen('\n')));,这是源代码,同时他采用了C+的模板语法 > template > inline basic_ostream<_CharT, _Traits>& > endl(basic_ostream<_CharT, _Traits>& __os) > { return flush(__os.put(__os.widen('\n'))); } 扩展知识: <<我们第一反应是左移操作符,在C++中他使用了重载概念,这是操作符重载,和Java的重载不同的是,他能函数和操作符重载 重载的<<源代码: // Partial specializations > template > inline basic_ostream& > operator<<(basic_ostream& ___out, const char* __s) > { > if (!__s) > ___out.setstate(ios_base::badbit); > else > __ostream_insert(___out, __s, > static_cast(_Traits::length(__s))); > return ___out; > } 其中**operator<<**是重载**<<**的运算符,同样可以operator+,则是重载+这个运算符 这里详细讲解一下<<重载和源代码的解释 **if (!__s) ___out.setstate(ios_base::badbit);** 这个语句告诉我们,判断传入的值是否为空,如果是空则返回baabit(标识流错误),倘若正确的就可以开始执行: **else __ostream_insert(___out, __s, static_caststreamsize(_Traits::length()__s)); return ___out;** 这个语句告诉我们,如果不是空则会插入值,__s(指的是传入的const char的指针) **而后调用__ostream_insert,并调用静态成员static_cast,同时调用_Traits::length()__s),返回__s的字符串长度** 同时使 static_cast将返回值改为*streamsize*类型 **而Traits类型是用于在编译时确定char类型的特征集(traits)的类型参数** *其中 template关键字是模板,typename定义一个类型名* inline则是在函数调用时,将这个函数代码插入函数调用的位置,避免函数调用的开销 而*inline basic_ostreamchar,&*则是标识运算符返回ostream的返回类型,同时*basic_ostreamchar,&*又是一个泛型,他用于输出char类型的输出流 --- #### 自己实现一个输出功能 ``` // 我们尝试简单魔改一下<<运算符,调用它的字符串会自动加上StarYuhen is: ,如果没有声明命名空间会告诉你编译器不知道调用哪个,我们可以写个命名空间 namespace YuhenStream { // template // std::ostream &operator<<(std::ostream output, const T &value) { // output << 'is StarYuhen' << value; // return output; // } // class YuhenStreamBuf : public std::streambuf 这一句话申明YuhenStreamBuf继承std::streambuf,相当于Java的extends class YuhenStreamBuf : public std::streambuf { // public标识共有 public: YuhenStreamBuf() { setp(buffer, buffer + bufferSize - 1); } // 保护 protected: virtual int_type overflow(int_type ch = traits_type::eof()) { if (ch != traits_type::eof()) { *pptr() = ch; pbump(1); } return flushBuffer(); } // 虚函数 virtual int sync() { return flushBuffer(); } // 私有 private: int flushBuffer() { if (pbase() == pptr()) { return 0; } *pptr() = '\0'; std::cout << "StarYuhen is:" << buffer; setp(buffer, buffer + bufferSize - 1); return 0; } // 静态常量 static const int bufferSize = 64; char buffer[bufferSize]; }; // 模板函数 template YuhenStreamBuf &operator<<(YuhenStreamBuf &out, const T &value) { std::ostringstream ss; ss << value; std::string strValue = ss.str(); out.sputn(strValue.c_str(), strValue.size()); return out; } // 定义两个类型对象 YuhenStreamBuf yuhenStreamBuf; std::ostream yuhenStream(&yuhenStreamBuf); } ``` Loading... ### 前言 我学习C++的时候想要了解深入一点的知识,又由于我C++是零基础,同时C也和零基础差不多,但是个人学习风格习惯,喜欢深入学习,于是从C++ Primer plus 5的一个简单 std::cout << "Hello, World!" << std::endl;** 开始了深入理解。 [源代码地址](https://github.com/StarYuhen/Daily_Practice/blob/master/C%2B%2B/C%2B%2B%20Primer%20plus5ChapterTwo/StdCout.cpp) #### AI阅读文章总结 这篇文章主要讲解了 C++ 中的输出流对象 std::cout 和相关的操作符重载。 首先,文章介绍了 std::cout 对象的原理,以及如何使用 << 插入运算符将字符串插入到输出流中。 其次,文章讲解了 std::endl 的作用,即在输出流中添加一个换行符,以及其源代码中使用的 C++ 模板语法。 接着,文章详细介绍了 << 运算符的重载概念和相关的源代码解释,以及 C++ 中如何使用模板来确定字符类型的特征集。 最后,文章通过自己实现一个输出功能,展示了如何使用命名空间和类来定制自己的输出流。 #### std::cout << "Hello, World!" << std::endl; 解析: 原理: 使用iostream库,同时导入也可以称之为iostream.h 的预处理 包含istream and ostream 两个基类,既输入/输出流 std::cout << "Hello, World!" << std::endl; 这个语句 是因为我们使用了(输出流)cout对象,他在iostream库中,被命名为extern ostream cout;并且设置为导出值 而<<运算符是插入运算符,能将值插入左边的对象,这个语句将"Hello, World!"字符串插入std::cout的输出流对象 而std::endl则是标识一个换行符,模板语法 return flush(__os.put(__os.widen('\n')));,这是源代码,同时他采用了C+的模板语法 > template<typename _CharT, typename _Traits> > inline basic_ostream<_CharT, _Traits>& > endl(basic_ostream<_CharT, _Traits>& __os) > { return flush(__os.put(__os.widen('\n'))); } 扩展知识: <<我们第一反应是左移操作符,在C++中他使用了重载概念,这是操作符重载,和Java的重载不同的是,他能函数和操作符重载 重载的<<源代码: // Partial specializations > template<typename _Traits> > inline basic_ostream<char, _Traits>& > operator<<(basic_ostream<char, _Traits>& ___out, const char* __s) > { > if (!__s) > ___out.setstate(ios_base::badbit); > else > __ostream_insert(___out, __s, > static_cast<streamsize>(_Traits::length(__s))); > return ___out; > } 其中**operator<<**是重载**<<**的运算符,同样可以operator+,则是重载+这个运算符 这里详细讲解一下<<重载和源代码的解释 **if (!__s) ___out.setstate(ios_base::badbit);** 这个语句告诉我们,判断传入的值是否为空,如果是空则返回baabit(标识流错误),倘若正确的就可以开始执行: **else __ostream_insert(___out, __s, static_caststreamsize(_Traits::length()__s)); return ___out;** 这个语句告诉我们,如果不是空则会插入值,__s(指的是传入的const char的指针) **而后调用__ostream_insert,并调用静态成员static_cast,同时调用_Traits::length()__s),返回__s的字符串长度** 同时使 static_cast<streamsize>将返回值改为*streamsize*类型 **而Traits类型是用于在编译时确定char类型的特征集(traits)的类型参数** *其中 template关键字是模板,typename定义一个类型名* inline则是在函数调用时,将这个函数代码插入函数调用的位置,避免函数调用的开销 而*inline basic_ostreamchar,&*则是标识运算符返回ostream的返回类型,同时*basic_ostreamchar,&*又是一个泛型,他用于输出char类型的输出流 --- #### 自己实现一个输出功能 ``` // 我们尝试简单魔改一下<<运算符,调用它的字符串会自动加上StarYuhen is: ,如果没有声明命名空间会告诉你编译器不知道调用哪个,我们可以写个命名空间 namespace YuhenStream { // template<typename T> // std::ostream &operator<<(std::ostream output, const T &value) { // output << 'is StarYuhen' << value; // return output; // } // class YuhenStreamBuf : public std::streambuf 这一句话申明YuhenStreamBuf继承std::streambuf,相当于Java的extends class YuhenStreamBuf : public std::streambuf { // public标识共有 public: YuhenStreamBuf() { setp(buffer, buffer + bufferSize - 1); } // 保护 protected: virtual int_type overflow(int_type ch = traits_type::eof()) { if (ch != traits_type::eof()) { *pptr() = ch; pbump(1); } return flushBuffer(); } // 虚函数 virtual int sync() { return flushBuffer(); } // 私有 private: int flushBuffer() { if (pbase() == pptr()) { return 0; } *pptr() = '\0'; std::cout << "StarYuhen is:" << buffer; setp(buffer, buffer + bufferSize - 1); return 0; } // 静态常量 static const int bufferSize = 64; char buffer[bufferSize]; }; // 模板函数 template<typename T> YuhenStreamBuf &operator<<(YuhenStreamBuf &out, const T &value) { std::ostringstream ss; ss << value; std::string strValue = ss.str(); out.sputn(strValue.c_str(), strValue.size()); return out; } // 定义两个类型对象 YuhenStreamBuf yuhenStreamBuf; std::ostream yuhenStream(&yuhenStreamBuf); } ``` 最后修改:2023 年 04 月 07 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏