C++ 如何创建自己的 ostream/streambuf?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/524641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:47:12  来源:igfitidea点击:

How do I create my own ostream/streambuf?

c++ostreamstreambuf

提问by Luc Hermitte

For educational purposes I want to create a ostream and stream buffer to do:

出于教育目的,我想创建一个 ostream 和流缓冲区来执行以下操作:

  1. fix endians when doing << myVar;
  2. store in a deque container instead of using std:cout or writing to a file
  3. log extra data, such as how many times I did <<, how many times I did .write, the amount of bytes I written and how many times I flush(). But I do not need all the info.
  1. 在执行 << myVar 时修复字节序;
  2. 存储在双端队列容器中,而不是使用 std:cout 或写入文件
  3. 记录额外的数据,例如我做了多少次<<,我做了多少次.write,我写的字节数和我flush()的次数。但我不需要所有信息。

I tried overloading but failed horribly. I tried overloading write by doing

我尝试重载但失败了。我尝试通过执行重载写入

ostream& write( const char* s, streamsize n ) 

in my basic_stringstream2 class (I copied paste basic_stringstream into my cpp file and modified it) but the code kept using basic_ostream. I looked through code and it looks like I need to overload xsputn (which isn't mention on this page http://www.cplusplus.com/reference/iostream/ostream) but what else do I need to overload? and how do I construct my class (what does it need to inherit, etc)?

在我的 basic_stringstream2 类(我复制粘贴 basic_stringstream 到我的 cpp 文件并修改它)但代码继续使用 basic_ostream。我查看了代码,看起来我需要重载 xsputn (在此页面http://www.cplusplus.com/reference/iostream/ostream上没有提到)但是我还需要重载什么?以及如何构建我的类(它需要继承什么等)?

回答by Luc Hermitte

The canonical approach consists in defining your own streambuf. You should have a look at:

规范方法包括定义您自己的流缓冲。你应该看看:

回答by mandrake

For A+C) I think you should look at facets, they modify how objects are written as characters. You could store statistics here as well on how many times you streamed your objects. Check out How to format my own objects when using STL streams?for an example.

对于 A+C) 我认为你应该看看 facet,它们修改了对象作为字符的书写方式。您还可以在此处存储有关您流式传输对象的次数的统计信息。查看如何在使用 STL 流时格式化我自己的对象?举个例子。

For B) You need to create your own streambuf and connect your ostream to that buffer (constructor argument). See Luc's links+ Deriving new streambuf classes. In short you need to implement this for an ostream (minimum):

对于 B) 您需要创建自己的 streambuf 并将您的 ostream 连接到该缓冲区(构造函数参数)。请参阅Luc 的链接+派生新的流缓冲类。简而言之,您需要为 ostream(最低)实现这一点:

  • overflow (put a single char or flush buffer) (link)
  • xsputn (put a char array to buffer)(link)
  • sync (link)
  • 溢出(放置单个字符或刷新缓冲区)(链接
  • xsputn(将字符数组放入缓冲区)(链接
  • 同步(链接

回答by Sol

I'm not sure that what you want to do is possible. The <<operators are not virtual. So you could define yourstream &operator << (yourstream &strm, int i)to do what you want with the endian conversion and counting, and it will work when your code calls it directly. But if you pass a yourstream object into a function that expects an ostream, any time that function calls <<, it will go to the original ostream version instead of yours.

我不确定你想做的事情是否可行。该<<运营商不虚。因此,您可以定义yourstream &operator << (yourstream &strm, int i)使用字节序转换和计数做您想做的事情,并且当您的代码直接调用它时它会起作用。但是,如果您将 yourstream 对象传递给需要 ostream 的函数<<,则该函数在任何时候调用,它都会转到原始 ostream 版本而不是您的版本。

As I understand it, the streams facilities have been set up so that you can "easily" define a new stream type which uses a different sort of buffer (like, say, a deque of chars), and you can very easily add support for outputting your own classes via <<. I don't think you are intended to be able to redefine the middle layer between those.

据我了解,已经设置了流设施,以便您可以“轻松”定义使用不同类型缓冲区(例如,字符双端队列)的新流类型,并且您可以非常轻松地添加对通过<<. 我不认为您打算重新定义它们之间的中间层。

And particularly, the entire point of the <<interface is to provide nicely formatted text output, while it sounds like you actually want binary output. (Otherwise the reference to "endian" makes no sense.) Even assuming there is some way of doing this I don't know, it will produce awkward binary output at best. For instance, consider the end user overload to output a point in 3D space. The end user version of <<will probably do something like << '(' << x << ", " << y << ", " << z << ')'. That will look nice in a text stream, but it's a lot of wasted and completely useless characters in a binary stream, which would ideally just use << x << y << z. (And how many calls to <<should those count as?)

特别是,<<界面的全部意义在于提供格式良好的文本输出,而听起来您实际上想要二进制输出。(否则对“endian”的引用是没有意义的。)即使假设有某种我不知道的方法,它充其量也会产生尴尬的二进制输出。例如,考虑最终用户在 3D 空间中输出一个点的过载。的最终用户版本<<可能会执行类似<< '(' << x << ", " << y << ", " << z << ')'. 这在文本流中看起来不错,但在二进制流中它有很多浪费和完全无用的字符,理想情况下只使用<< x << y << z. (这些电话<<应该算作多少?)