前言

我学习C++的时候想要了解深入一点的知识,又由于我C++是零基础,同时C也和零基础差不多,但是个人学习风格习惯,喜欢深入学习,于是从C++ Primer plus 5的一个简单

std::cout << "Hello, World!" << std::endl;**

开始了深入理解。

源代码地址

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<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(_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<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 日
如果觉得我的文章对你有用,请随意赞赏