2013-02-24 2 views
1

들여 쓰기 된 텍스트를 출력하고 들여 쓰기 수준을 변경할 수있는 조작기가있는 사용자 지정 스트림 클래스를 작성했습니다. 들여 쓰기 작업은 모두 스트림 클래스에서 사용하는 사용자 지정 스트림 버퍼 클래스로 구현됩니다. 버퍼가 작동 중입니다. 즉, 출력에서 ​​텍스트가 들여 쓰기되어 있지만 조작 할 수 없습니다. 이 매개 변수로 함수에 걸릴 수 있다는 것을 의미사용자 지정 스트림 클래스에 대한 조작자 작성

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

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

: ostream에가 (내 수업의 연장) 운영자 같은 < < 과부하 어떻게 많은 장소에서 읽고 있었다. 그렇다면 왜 내 "들여 쓰기"또는 "deindent"스트림 함수가 인식되지 않습니까? 나는 연산자의 오버로드를해야한다고 확신한다. < <,하지만 나는 필요가 없다. 내 코드는 아래를 참조하십시오.

#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; 
} 

고마워요!

+0

클래스 외부의 자유 함수 여야합니다. 물론 파생 된 클래스의 정보에 액세스해야하므로 사용하기가 까다로울 수 있습니다. –

+0

글쎄, 포인터 - 투 - 멤버 함수를 사용하고 싶지는 않습니다. –

답변

4

사용자 조작자는 ostream& 유형의 인수를 하나만 허용하는 함수로 선언해야합니다. 그러나 구성원 인 기능을 사용하는 경우 암시적인 this 인수가 함수에 전달된다는 것을 알고 있습니다. 또한

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; 
} 

당신이 정말로 원하는 경우 : 그것 개인 회원 ib에 액세스 할 수 있도록 따라서

, 당신은 오히려 클래스의 friend을, 무료, 비 멤버 함수로 조작을 선언해야 함수가 멤버로, 당신은 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; 
} 
+0

완벽하게 작동했습니다! 감사! – AlexSilva

+0

@AlexSilva : 다행스럽게도 :-) –

관련 문제