C++ 如何创建在C+中处理输入和输出的流+;?

C++ 如何创建在C+中处理输入和输出的流+;?,c++,iostream,c++-faq,streambuf,C++,Iostream,C++ Faq,Streambuf,我试图创建一个同时作为输入和输出流的类(比如std::cout和std::cin)。我试图重载运算符 ,但是我理解编写这样的代码是不明智的(因为这是一种重写C++流的方法),并且在类如 STD::Basic SyoSoist, STD::Basic IoSooS代码> STD::Basic SistReMe>代码可在C++标准库中使用,因为我必须为每个类型重载运算符。所以,我试着这样定义我的类: #包括 类MyStream:public std::basic_iostream{ 公众: MyS

我试图创建一个同时作为输入和输出流的类(比如
std::cout
std::cin
)。我试图重载运算符<代码> <代码和代码> <代码>,但是我理解编写这样的代码是不明智的(因为这是一种重写C++流的方法),并且在类如 STD::Basic SyoSoist,<代码> STD::Basic IoSooS代码> STD::Basic SistReMe>代码可在C++标准库中使用,因为我必须为每个类型重载运算符。所以,我试着这样定义我的类:

#包括
类MyStream:public std::basic_iostream{
公众:
MyStream():std::basic_iostream(stream_buffer){}
};
我的问题在于
std::basic\u iostream
构造函数中的第一个参数。截至,
std::basic\u iostream::basic\u iostream
获取一个指向从
std::basic\u streambuf
派生的流缓冲区的指针:

explicit basic_iostream(std::basic_streambuf*sb);
我已经阅读并尝试了来自的例子。它说我必须传递一个指向流缓冲区的指针,有三种方法:

  • 在类初始化之前创建流缓冲区
  • 从另一个流获取流缓冲区(使用
    rdbuf()
    或类似成员)
  • 基本\u streambuf
    对象定义为受保护或私有成员
最后一个选项最适合我的目的,但是如果我直接从
std::basic_streambuf
类创建一个对象,它不会做任何事情,是吗?因此,我定义了另一个类,它派生自
std::basic\u streambuf
。但这一次我无法理解要定义哪些函数,因为我不知道在插入、提取和刷新数据时调用哪个函数

如何创建具有自定义功能的流?



<强>注意,这是一个试图创建C++流和流缓冲区的标准指南。

< P>创建一个行为类似流的类是很容易的。假设我们希望创建名为
MyStream
的类,该类的定义将非常简单:

#include//class“basic_iostream”在这里定义
类MyStream:public std::basic_iostream{
私人:
std::basic_streambuf buffer;//您的streambuf对象
公众:
MyStream():std::basic_iostream(&buffer){}//请注意,与
};
类的构造函数应该使用指向自定义
std::basic\u streambuf
对象的指针调用
std::basic\u streambuf
的构造函数
std::basic_streambuf
只是一个定义流缓冲区结构的模板类。因此,您必须获得自己的流缓冲区。您可以通过两种方式获得:

  • 来自另一个流:每个流都有一个成员
    rdbuf
    ,该成员不接受任何参数,并返回指向它所使用的流缓冲区的指针。例如:
  • 。。。
    std::basic_streambuf*buffer=std::cout.rdbuf();//从std::cout获取
    ...
    
  • 创建您自己的:您始终可以通过从
    std::basic_streambuf
    派生来创建缓冲区类,并根据需要对其进行自定义
  • 现在我们定义并实现了
    MyStream
    类,我们需要流缓冲区。让我们从上面选择选项2,创建我们自己的流缓冲区,并将其命名为
    MyBuffer
    。我们需要:

  • 构造函数初始化对象
  • 通过程序临时存储输出的连续内存块
  • 用于临时存储用户(或其他对象)输入的连续内存块
  • 方法
    溢出
    ,当用于存储输出的分配内存已满时调用该方法
  • 方法
    underflow
    ,当程序读取所有输入并请求更多输入时调用该方法
  • 方法
    sync
    ,刷新输出时调用该方法
  • 因为我们知道创建流缓冲区类需要什么,所以让我们声明它:

    class MyBuffer:public std::basic\u streambuf{
    私人:
    char-inbuf[10];
    char-f[10];
    int sync();
    int_型溢出(int_型ch);
    int_型底流();
    公众:
    MyBuffer();
    };
    
    这里的
    inbuf
    extruf
    是两个数组,分别存储输入和输出
    int\u type
    是一种特殊类型,类似于char,创建时支持多种字符类型,如
    char
    wchar\u t

    在我们开始实现缓冲区类之前,我们需要知道缓冲区将如何工作

    为了理解缓冲区是如何工作的,我们需要知道数组是如何工作的。数组不是什么特殊的东西,只是指向连续内存的指针。当我们声明一个包含两个元素的
    char
    数组时,操作系统会为我们的程序分配
    2*sizeof(char)
    内存。当我们使用
    array[n]
    访问数组中的元素时,它将转换为
    *(array+n)
    ,其中
    n
    是索引号。将
    n
    添加到数组时,它会跳到下一个
    n*sizeof()
    (图1)。如果你不知道什么是指针算法,我建议你在继续之前先学习一下。对初学者有一个很好的指导

                 array    array + 1
                   \        /
    ------------------------------------------
      |     |     | 'a' | 'b' |     |     |
    ------------------------------------------
        ...   105   106   107   108   ...
                     |     |
                     -------
                        |
                memory allocated by the operating system
    
                         figure 1: memory address of an array
    
    现在我们对指针了解很多,让我们看看流缓冲区是如何工作的。我们的缓冲区包含两个数组
    inbuf
    extruf
    。但是标准库如何知道输入必须存储到
    inbuf
    ,输出必须存储到
    extruf
    ?所以,有两个区域称为get区域和put区域,分别是输入和输出区域

    Put区域由以下参数指定:
      pbase()                         pptr()                       epptr()
         |                              |                             |
    ------------------------------------------------------------------------
      | 'H' | 'e' | 'l' | 'l' | 'o'  |     |     |     |     |     |     |
    ------------------------------------------------------------------------
         |                                                      |
         --------------------------------------------------------
                                     |
                       allocated memory for the buffer
    
               figure 2: output buffer (put area) with sample data
    
      eback()                         gptr()                       egptr()
         |                              |                             |
    ------------------------------------------------------------------------
      | 'H' | 'e' | 'l' | 'l' | 'o'  | ' ' | 'C' | '+' | '+' |     |     |
    ------------------------------------------------------------------------
         |                                                      |
         --------------------------------------------------------
                                     |
                       allocated memory for the buffer
    
               figure 3: input buffer (get area) with sample data