Perché `std :: basic_ios` ha un costruttore pubblico?


15

std::basic_iosha un costruttore pubblico :

explicit basic_ios (std::basic_streambuf<CharT,Traits>* sb);

IMO, l'unica ragione per cui una classe ha un costruttore pubblico è usare un'istanza autonoma di quella classe in un programma. Se una classe esiste solo per far discendere altre classi da essa (come sembra essere il caso basic_ios), dovrebbero essere tutti i costruttori della classe protected. I costruttori di std::ios_basesono tutti protetti. Ma, per qualche motivo, i progettisti dello standard hanno reso pubblico questo unico costruttore basic_ios.

basic_iosviene utilizzato come classe di base per diversi tipi di stream e non riesco a immaginare un caso d'uso in cui ne avresti avuto uno che non fosse almeno un basic_istreamo basic_ostream. Ce n'è uno?

Risposte:


1

L'altro motivo per cui una classe deve avere un costruttore pubblico è avere questa firma del costruttore disponibile per costruire un oggetto derivato:

struct B{
  B(int);
  protected:
  ~B();
  };

 struct A:B{
    private://no effect.
    using B::B;

    public:
    A(void*);
    };

 A a(10);

Il costruttore deve essere pubblico nella classe base perché una dichiarazione di utilizzo di un costruttore base non modifica l'accessibilità del costruttore ereditato.


2
Sembra risonabile, tranne Afaik, il basic_iosctor che prende un basic_streambuf*è stato pubblico da prima che tu potessi farlo using B::B;. Mi aspetto che le vecchie implementazioni abbiano appena avuto un proxy ctor: A(int x) : B(x) {}- che funziona benissimo anche se Bctor lo è protected.
Ted Lyngmo,

0

Quello che non ho notato è stato std::basic_istream, std::basic_ostreame std::basic_iostreamaveva anche costruttori pubblici (ognuno prende a std::basic_streambuf*).

Ciò consente un analogo di programmazione generica del polimorfismo, nella stessa ottica del linguaggio del brufolo.

Cioè, in questo modo è possibile creare un tipo streambuf specializzato e utilizzarlo in un basic_[io] streamsenza dover creare classi stream specializzate. (La funzionalità è limitata: non è possibile assegnare un nuovo buffer allo stesso flusso e tenere traccia esternamente della durata e della proprietà del buffer).

Gli basic_[io] fstreame basic_[io] specializzati stringstreamcontengono ciascuno un'istanza completa del tipo di buffer associato. Ciò significa che un'istanza di un tipo di flusso specializzato funzionerà solo con il suo buffer interno e non con un altro, nemmeno uno dello stesso tipo. L'uso di un basic_[io] grezzo streamè una soluzione (ingombrante) a questo.

template<class C, class TR>
class snazzy_filebuf: public std::basic_streambuf<C, TR>
{
 protected:
   typename TR::int_type overflow(TR::int_type) override;
   typename TR::int_type underflow(TR::int_type) override;
   typename TR::int_type pbackfail(TR::int_type) override;
 public:
   snazzy_filebuf();
};

.....
snazzy_filebuf<char> buf;
std::basic_ostream<char> o_s(&buf); 

o_s << "Hello, world\n";
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.