2012-04-24 11 views
5

Estoy escribiendo una clase que tiene varios mensajes de salida. Quiero que esta clase sea general y independiente de la plataforma, así que estoy pensando en pasarle una referencia basic_ostream y puede volcar todos los mensajes en la transmisión. Al hacer esto, si la clase se usa en un programa de consola, puedo pasarle std :: cout y mostrarla en la ventana de la consola.¿Cómo derivar de C++ std :: basic_ostream y hacer que el << operador sea virtual?

O podría pasar un ostream derivado y redirigir el mensaje a algunos componentes de la interfaz de usuario, p. ¿Cuadro de lista? El único problema es que el insertador de datos operator << no es una función virtual. Si paso la referencia de clase derivada a él, solo se llamará al operador basic_ostream < <.

¿Hay alguna solución para esto? propia respuesta

+3

¿Por qué no utilizar la interfaz genérica 'std :: ostream' y cambiar el' stre subyacente ambuf' basado en su contexto? No se necesitan funciones virtuales. – mavam

+3

No puede hacer que una función no miembro sea virtual. 'operator <<' no es miembro de 'basic_ostream', sino una función gratuita. –

+0

@MatthiasVallentin: Pero necesito pasar la referencia de la clase base std :: ostream a mi clase. En tal caso, mi clase derivada del operador << de ostream 'nunca será llamada. –

Respuesta

1

Nan Zhang, publicado originalmente como parte de la pregunta:

Seguimiento: OK, aquí está el std :: streambuf derivada que implementa la funcionalidad requerida:

class listboxstreambuf : public std::streambuf { 
public: 
    explicit listboxstreambuf(CHScrollListBox &box, std::size_t buff_sz = 256) : 
      Scrollbox_(box), buffer_(buff_sz+1) { 
     char *base = &buffer_.front(); 
     //set putbase pointer and endput pointer 
     setp(base, base + buff_sz); 
    } 

protected: 
    bool Output2ListBox() { 
     std::ptrdiff_t n = pptr() - pbase(); 
     std::string temp; 
     temp.assign(pbase(), n); 
     pbump(-n); 
     int i = Scrollbox_.AddString(temp.c_str()); 
     Scrollbox_.SetTopIndex(i); 
     return true; 
    } 

private: 
    int sync() { 
     return Output2ListBox()? 0:-1; 
    } 

    //copying not allowed. 
    listboxstreambuf(const listboxstreambuf &); 
    listboxstreambuf &operator=(const listboxstreambuf &); 

    CHScrollListBox &Scrollbox_; 
    std::vector<char> buffer_; 
}; 

Para utilizar esta clase solo crea un std :: ostream e inicializa con este buffer

std::ostream os(new listboxstreambuf(some_list_box_object)); 
Cuestiones relacionadas