C++ 使用xsputn和溢出继承ostream和streambuf问题

C++ 使用xsputn和溢出继承ostream和streambuf问题,c++,iostream,ostream,streambuf,C++,Iostream,Ostream,Streambuf,我一直在研究如何创建自己的ostream,以及如何使用streambuf来处理ostream的缓冲区。实际上,我的大部分工作正常,我可以插入(你在做什么不太清楚,尽管听起来很粗略 好的。请确定:您的ostream所做的就是提供 方便的构造函数创建和安装您的streambuf, 一个析构函数,可能是rdbuf的一个实现 处理正确类型的缓冲区。假设这是真的: 在streambuf中定义xsputn纯粹是一种优化。 您必须定义的关键函数是溢出 溢出的实现只需要一个字符,并且 将其输出到接收器。除此之外

我一直在研究如何创建自己的ostream,以及如何使用streambuf来处理ostream的缓冲区。实际上,我的大部分工作正常,我可以插入(你在做什么不太清楚,尽管听起来很粗略 好的。请确定:您的
ostream
所做的就是提供 方便的构造函数创建和安装您的
streambuf
, 一个析构函数,可能是
rdbuf
的一个实现 处理正确类型的缓冲区。假设这是真的: 在
streambuf
中定义
xsputn
纯粹是一种优化。 您必须定义的关键函数是
溢出
溢出
的实现只需要一个字符,并且 将其输出到接收器。除此之外的一切都是优化: 例如,如果需要,可以使用
setp
;设置缓冲区 只有在缓冲区被调用时,才会调用此溢出 已满或已请求同花顺。在这种情况下,您必须 输出缓冲区(使用
pbase
pptr
获取 (streambuf基类初始化 用于创建0长度缓冲区的指针,因此
溢出将
为每个字符调用。)您可能需要的其他函数
要在(非常)特定的情况下覆盖:

imbue
:如果您出于某种原因需要区域设置(记住这一点) 当前字符编码是区域设置的一部分。)

setbuf
:允许客户机代码指定缓冲区 通常不值得麻烦,但你可能有特殊的 要求。)

seekoff
:支持查找。我从未在任何一个应用程序中使用过此功能 我的
streambuf
s,因此我无法提供任何信息 你可以在标准中阅读

sync
:在flush时调用,应在 缓冲区到接收器。如果您从未调用
setp
(因此没有 缓冲区),您始终处于同步状态,这可能是不可操作的。
overflow
uflow
可以调用这个,或者两者都可以调用一些 独立功能。(关于
sync
uflow
是指只有在存在时才会调用
uflow
缓冲区,如果缓冲区为空,则永远不会调用它。 如果客户端代码刷新流,将调用
sync
。)

在编写自己的流时,除非性能要求 否则,我将保持它的简单性,只覆盖
溢出
。 如果性能决定了缓冲区,我通常会将代码放入 将缓冲区刷新为单独的
写入(地址、长度)
功能,并沿线路执行
溢出
同步
其中:

一般来说,我不会为
xsputn
操心,但是如果您的客户 代码输出了很多长字符串,这可能很有用。 像这样的事情应该可以做到:

streamsize xsputn(char const* p, streamsize n)
{
    streamsize results = 0;
    if ( pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed ) {
        if ( write(p, n) != failed ) {
            results = n;
        }
    }
    setp( buffer, buffer + bufferSize - 1 );
    return results;
}

这基本上就是我现在正在做的,我想知道的是,是否有任何方法来告诉溢出将被调用多少次,或者最后一个字符何时经过。例如,如果我使用mystream,代码无法提前知道客户端代码将要做什么,或者它将被调用多少次。您可以做的是在
ostream
上的et
unitbuf
:这将导致在每个
操作结束时调用
sync
。这正是我所需要的!将此标记为答案,现在还不能投票,但一旦获得足够的代表,我会回来这样做。非常感谢。此设计的部分问题在于假设当您有
std::complex::operator时
streamsize xsputn(char const* p, streamsize n)
{
    streamsize results = 0;
    if ( pptr() == pbase()
            || write( pbase(), pptr() - pbase() ) != failed ) {
        if ( write(p, n) != failed ) {
            results = n;
        }
    }
    setp( buffer, buffer + bufferSize - 1 );
    return results;
}