Mengapa `std :: basic_ios` memiliki konstruktor publik?

15

std::basic_iosmemiliki konstruktor publik :

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

IMO, satu-satunya alasan bagi kelas untuk memiliki konstruktor publik adalah untuk menggunakan contoh mandiri dari kelas itu dalam suatu program. Jika suatu kelas ada hanya untuk memiliki kelas lain turun dari itu (seperti yang tampaknya terjadi basic_ios), semua konstruktor kelas harus protected. Konstruktor std::ios_basesemua dilindungi. Tetapi, untuk beberapa alasan, para perancang standar menjadikannya sebagai konstruktor basic_iospublik.

basic_iosdigunakan sebagai kelas dasar untuk beberapa jenis aliran, dan saya tidak bisa membayangkan kasus penggunaan di mana Anda akan memiliki satu yang setidaknya basic_istreamatau tidak basic_ostream. Apakah ada satu?

Spencer
sumber

Jawaban:

1

Alasan lain untuk kelas untuk memiliki konstruktor publik adalah untuk memiliki tanda tangan konstruktor ini tersedia untuk membangun objek turunan:

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

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

    public:
    A(void*);
    };

 A a(10);

Konstruktor harus bersifat publik di kelas dasar karena deklarasi penggunaan konstruktor dasar tidak mengubah aksesibilitas konstruktor yang diwarisi.

Oliv
sumber
2
Tampaknya beresonansi, kecuali afaik, basic_iosaktor yang mengambil basic_streambuf*telah publik sejak sebelum Anda bisa melakukannya using B::B;. Saya berharap bahwa implementasi lama hanya memiliki ctor proxy: A(int x) : B(x) {}- yang berfungsi dengan baik bahkan jika Bctor adalah protected.
Ted Lyngmo
0

Apa yang saya gagal perhatikan adalah bahwa std::basic_istream, std::basic_ostreamdan std::basic_iostreamjuga memiliki konstruktor publik (masing-masing membutuhkan a std::basic_streambuf*).

Hal ini memungkinkan analog pemrograman-generik polimorfisme, dengan nada yang sama dengan ungkapan pimpl.

Artinya, dengan cara ini Anda dapat membuat tipe streambuf khusus dan menggunakannya dalam basic_[io] streamtanpa harus membuat kelas aliran khusus. (Fungsinya terbatas: Anda tidak dapat menetapkan buffer baru ke stream yang sama, dan Anda harus melacak secara eksternal masa pakai dan kepemilikan buffer).

The khusus basic_[io] fstreamdan basic_[io] stringstreammasing-masing berisi contoh lengkap dari jenis buffer terkait. Ini berarti sebuah instance dari tipe stream khusus hanya akan bekerja dengan buffer internal dan bukan yang lain, bahkan tidak satu dari tipe yang sama. Menggunakan basic_[io] mentah streamadalah solusi (kikuk) untuk ini.

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";
Spencer
sumber