C++ 如果没有',`basic_streambuf`是否创建自己的获取/放置区域;在派生类实现中不这样做吗?

C++ 如果没有',`basic_streambuf`是否创建自己的获取/放置区域;在派生类实现中不这样做吗?,c++,streambuf,C++,Streambuf,我已经多次看过创建自定义streambuf的说明:您所需要做的就是在std::basic_streambuf的后代中正确地实现溢出、下溢、和pbackfail,并且您可以创建一个使用它格式化数据的流。这三个例程定义了自定义流的“受控序列” 但是在std::basic_streambuf的受保护成员列表中潜伏着其他怪物,即setg和setp。这些设置了输入和输出的缓冲区。获取和设置数据的公共成员尝试在遵循受控序列之前首先访问这些区域 对于两个不同的定制streambuf,如果流设置自己的get/p

我已经多次看过创建自定义streambuf的说明:您所需要做的就是在
std::basic_streambuf
的后代中正确地实现
溢出
下溢
、和
pbackfail
,并且您可以创建一个使用它格式化数据的流。这三个例程定义了自定义流的“受控序列”

但是在
std::basic_streambuf
的受保护成员列表中潜伏着其他怪物,即
setg
setp
。这些设置了输入和输出的缓冲区。获取和设置数据的公共成员尝试在遵循受控序列之前首先访问这些区域

对于两个不同的定制streambuf,如果流设置自己的get/put区域,则可能会出现问题。因此,我希望这样的streambufs避免使用get/put区域,并且总是使用
溢出
下溢
,以及
pbackfail
,而不使用任何中间缓冲

对于一个简单的简单示例,如果您正在包装另一个streambuf,
underflow
的实现可能如下所示:

template <class C, class TR>
typename TR::int_type wrapping_streambuf<C, TR>::underflow()
{
 return m_wrapped_streambuf->sgetc();
}
模板
typename TR::int_type wrapping_streambuf::underflow()
{
返回m_wrapped_streambuf->sgetc();
}
让包装好的streambuf处理所有的脏活。 下面是另一个计算行数的简单示例:

template <class C, class TR>
typename TR::int_type tracking_streambuf<C, TR>::uflow()
{
  auto rv = m_wrapped_streambuf->sbumpc();
  if (rv == (TR::int_type)'\n') ++ m_input_line_count;
  return rv;
}
模板
typename TR::int_type tracking_streambuf::uflow()
{
自动rv=m_-wrapped_-streambuf->sbumpc();
如果(rv==(TR::int_type)'\n')++m_输入线计数;
返回rv;
}
对于这样的流,没有有用的
setg
实现,因为您无法获取包装缓冲区的内部get区域。对于
tracked\u streambuf
,强制设置get/put区域将使与流的逻辑顺序同步的计数行变得不可能

我认为答案是永远不要在后代类中调用
setg
setp
。事实上,它们可能应该覆盖
setg
setp
gbump
pbump
来抛出异常

查看
标题,我看到一个定制的streambuf
在我最喜欢的库中,如果我这样做的话,实现可能会按照我想要的方式工作(有空gptr/pptr的检查)。但这是保证吗

std::basic_streambuf的默认构造函数将定义get和put区域的六个指针设置为空指针值,因此默认情况下它不会“创建自己的get/put区域”

函数
setg
setp
gbump
pbump
是受保护的成员,默认情况下不会被公共成员函数调用,因此您不必担心它们。当然,重写它们以抛出异常并不坏

此外,没有中间缓冲区的自定义流缓冲区类也应重写该函数,该函数可由公共成员函数调用,以处理需要提升get指针值的溢出情况。默认情况下,其默认行为是(引用自):

默认行为:调用
underflow()
。如果
underflow()
返回
特征​::​eof()
,返回
特征​::​eof()
。否则,返回
traits的值​::​输入类型(*gptr())
,并为输入序列增加下一个指针的值


因此,如果您不重写此函数,它将导致通过空指针间接寻址的未定义行为。

回答得很好,关于
uflow
的观点也很好。听起来你在引用标准(你用了‘shall’而不是‘must’)。即使是非规范性注释,您是否可以使用相关章节号进行更新?@Spencer标准没有明确建议覆盖
uflow
(至少我没有发现),而。但你是对的,我使用“shall”的习惯来自标准的措辞只是提醒一下:我把“get/set”改为“get/put”。