문제

나는 인터넷 검색을 해왔고 이것에 대한 간단한 대답을 찾을 수 없습니다. STL이 일반적으로 그렇듯이 간단해야합니다.

STD :: Ostream에서 공개적으로 상속되는 Myostream을 정의하고 싶습니다. 내 스트림에 무언가가 기록 될 때마다 foo ()에게 전화하고 싶다고 가정 해 봅시다.

class MyOStream : public ostream {
public:
  ...
private:
   void foo() { ... }
}

나는 타조의 공개 인터페이스가 가치가 없다는 것을 이해합니다. 어떻게 할 수 있습니까? 클라이언트가 연산자 << 및 write () 및 myostream에서 ()를 모두 사용할 수 있고 내 클래스의 확장 된 능력을 사용할 수 있기를 원합니다.

도움이 되었습니까?

해결책

불행히도 간단한 질문이 아닙니다. 당신이 파생해야 할 수업은 basic_ 다음과 같은 클래스 basic_ostream. 그러나 스트림으로부터의 파생은 원하는 것이 아닐 수도 있고, 대신 스트림 버퍼에서 파생 한 다음이 클래스를 사용하여 기존 스트림 클래스를 인스턴스화 할 수 있습니다.

전체 지역은 복잡하지만 그것에 대한 훌륭한 책이 있습니다. 표준 C ++ ioStreams 및 로케일, 더 이상 가기 전에 살펴 보는 것이 좋습니다.

다른 팁

나는 똑같은 일을하는 방법에 대해 머리를 돌리고 있었고 그것이 실제로 그렇게 어렵지 않다는 것을 알았습니다. 기본적으로 타조와 StreamBuf 객체를 서브 클래스하고 버퍼로 타조 자체를 구성합니다. std :: streamBuf의 가상 오버플로 ()는 스트림으로 전송 된 모든 문자에 대해 호출됩니다. 당신의 예를 맞추기 위해 나는 방금 foo () 함수를 만들어 그것을 불렀습니다.

struct Bar : std::ostream, std::streambuf
{
    Bar() : std::ostream(this) {}

    int overflow(int c)
    {
        foo(c);
        return 0;
    }


    void foo(char c)
    {
        std::cout.put(c);

    }
};

void main()
{
    Bar b;
    b<<"Look a number: "<<std::hex<<29<<std::endl;
}

오, 주요 기능이 실제 주요 기능이 아니라는 사실을 무시하십시오. 다른 곳에서 호출 된 네임 스페이스에 있습니다. P

비슷한 효과를 달성하기위한 또 다른 작업 해킹은 템플릿과 구성을 사용하는 것입니다.

class LoggedStream {
public:
  LoggedStream(ostream& _out):out(_out){}
  template<typename T>
  const LoggedStream& operator<<(const T& v) const {log();out << v;return *this;}
protected:
  virtual void log() = 0;
  ostream& out;
};

class Logger : LoggedStream {
  void log() { std::cerr << "Printing" << std::endl;}
};

int main(int,char**) {LoggedStream(std::cout) << "log" << "Three" << "times";}

이것이 올바른 솔루션인지는 모르겠지만 STD :: Ostream에서 상속했습니다. STD :: BASIC_STREAMBUF에서 상속 된 버퍼를 사용하고 한 번에 64 자 씩 (또는 플러시 된 경우 적은 경우) 실제 데이터 처리가 수행되는 일반적인 putchars () 메소드로 보냅니다. 또한 사용자 데이터를 제공하는 방법을 보여줍니다.

라이브 예

#include <streambuf>
#include <ostream>
#include <iostream>

//#define DEBUG

class MyData
{
    //example data class, not used
};

class MyBuffer : public std::basic_streambuf<char, std::char_traits<char> >
{

public:

    inline MyBuffer(MyData data) :
    data(data)
    {
        setp(buf, buf + BUF_SIZE);
    }

protected:

    // This is called when buffer becomes full. If
    // buffer is not used, then this is called every
    // time when characters are put to stream.
    inline virtual int overflow(int c = Traits::eof())
    {
#ifdef DEBUG
        std::cout << "(over)";
#endif
        // Handle output
        putChars(pbase(), pptr());
        if (c != Traits::eof()) {
            char c2 = c;
            // Handle the one character that didn't fit to buffer
            putChars(&c2, &c2 + 1);
        }
        // This tells that buffer is empty again
        setp(buf, buf + BUF_SIZE);

        return c;
    }

    // This function is called when stream is flushed,
    // for example when std::endl is put to stream.
    inline virtual int sync(void)
    {
        // Handle output
        putChars(pbase(), pptr());
        // This tells that buffer is empty again
        setp(buf, buf + BUF_SIZE);
        return 0;
    }

private:

    // For EOF detection
    typedef std::char_traits<char> Traits;

    // Work in buffer mode. It is also possible to work without buffer.
    static const size_t BUF_SIZE = 64;
    char buf[BUF_SIZE];

    // This is the example userdata
    MyData data;

    // In this function, the characters are parsed.
    inline void putChars(const char* begin, const char* end){
#ifdef DEBUG
        std::cout << "(putChars(" << static_cast<const void*>(begin) <<
            "," << static_cast<const void*>(end) << "))";
#endif
        //just print to stdout for now
        for (const char* c = begin; c < end; c++){
            std::cout << *c;
        }
    }

};

class MyOStream : public std::basic_ostream< char, std::char_traits< char > >
{

public:

    inline MyOStream(MyData data) :
    std::basic_ostream< char, std::char_traits< char > >(&buf),
    buf(data)
    {
    }

private:

    MyBuffer buf;

};

int main(void)
{
    MyData data;
    MyOStream o(data);

    for (int i = 0; i < 8; i++)
        o << "hello world! ";

    o << std::endl;

    return 0;
}

상속이 아닌 구성. 귀하의 클래스에는 "Traps"가 포함되어 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top