gpt4 book ai didi

c++ - 为自定义流类编写操纵器

转载 作者:行者123 更新时间:2023-11-30 02:00:32 26 4
gpt4 key购买 nike

我编写了一个自定义流类,它输出缩进文本并且具有可以更改缩进级别的操纵器。所有缩进工作都在流类使用的自定义流缓冲区类中实现。缓冲区正在工作(即文本在输出中缩进),但我无法让我的操纵器工作。我在很多地方读到 ostream(我的类扩展)如何像这样重载 operator<<:

ostream& ostream::operator << ( ostream& (*op)(ostream&))

{
// call the function passed as parameter with this stream as the argument
return (*op)(*this);
}

这意味着它可以接受一个函数作为参数。那么,为什么我的“缩进”或“缩进”流函数没有被识别?我确定我必须对运算符 << 进行一些重载,但我不需要这样做吗?请参阅下面的代码:

#include <iostream>
#include <streambuf>
#include <locale>
#include <cstdio>

using namespace std;

class indentbuf: public streambuf {

public:

indentbuf(streambuf* sbuf): m_sbuf(sbuf), m_indent(4), m_need(true) {}

int indent() const { return m_indent; }
void indent() { m_indent+=4; }
void deindent() { if(m_indent >= 4) m_indent-= 4; }

protected:

virtual int_type overflow(int_type c) {

if (traits_type::eq_int_type(c, traits_type::eof()))

return m_sbuf->sputc(c);

if (m_need)
{
fill_n(ostreambuf_iterator<char>(m_sbuf), m_indent, ' ');
m_need = false;
}

if (traits_type::eq_int_type(m_sbuf->sputc(c), traits_type::eof()))

return traits_type::eof();

if (traits_type::eq_int_type(c, traits_type::to_char_type('\n')))

m_need = true;

return traits_type::not_eof(c);
}

streambuf* m_sbuf;
int m_indent;
bool m_need;
};

class IndentStream : public ostream {
public:
IndentStream(ostream &os) : ib(os.rdbuf()), ostream(&ib){};

ostream& indent(ostream& stream) {
ib.indent();
return stream;
}

ostream& deindent(ostream& stream) {
ib.deindent();
return stream;
}

private:
indentbuf ib;
};

int main()
{
IndentStream is(cout);
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << deindent << endl;
return 0;
}

谢谢!

最佳答案

你的操纵器应该被声明为一个函数,它只接受一个ostream&类型的参数。但是,如果您将它设为成员 函数,您就会知道还有一个隐式的this 参数被传递给该函数。

因此,您应该将操纵器声明为一个自由的非成员函数,使其成为您类的友元,以便它可以访问其私有(private)成员ib:

class IndentStream : public ostream {
public:
IndentStream(ostream &os) : ib(os.rdbuf()), ostream(&ib){};

ostream& indent(ostream& stream) {
ib.indent();
return stream;
}

friend ostream& deindent(ostream& stream);
// ^^^^^^

private:
indentbuf ib;
};

ostream& deindent(ostream& stream)
{
IndentStream* pIndentStream = dynamic_cast<IndentStream*>(&stream);
if (pIndentStream != nullptr)
{
pIndentStream->ib.deindent();
}

return stream;
}

int main()
{
IndentStream is(cout);
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << deindent << endl;
is << "31 hexadecimal: " << hex << 31 << endl;
return 0;
}

或者,如果你真的想让你的函数成为成员,你可以让它成为static:

class IndentStream : public ostream {
public:
IndentStream(ostream &os) : ib(os.rdbuf()), ostream(&ib){};

ostream& indent(ostream& stream) {
ib.indent();
return stream;
}

static ostream& deindent(ostream& stream)
{
IndentStream* pIndentStream = dynamic_cast<IndentStream*>(&stream);
if (pIndentStream != nullptr)
{
pIndentStream->ib.deindent();
}

return stream;
}

private:
indentbuf ib;
};

但是,这会强制您使用限定名称来引用它:

int main()
{
IndentStream is(cout);
is << "31 hexadecimal: " << hex << 31 << endl;
is << "31 hexadecimal: " << hex << 31 << IndentStream::deindent << endl;
// ^^^^^^^^^^^^^^
is << "31 hexadecimal: " << hex << 31 << endl;
return 0;
}

关于c++ - 为自定义流类编写操纵器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15053753/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com