Почему у `std :: basic_ios` есть открытый конструктор?

15

std::basic_iosимеет открытый конструктор :

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

IMO, единственная причина, по которой у класса есть открытый конструктор, - это использование автономного экземпляра этого класса в программе. Если класс существует только для того, чтобы другие классы происходили от него (как, кажется, имеет место basic_ios), все конструкторы класса должны быть protected. Все конструкторы std::ios_baseзащищены. Но, по какой-то причине, разработчики стандарта сделали этот конструктор basic_iosпубличным.

basic_iosиспользуется в качестве базового класса для нескольких типов потоков, и я не могу представить вариант использования, в котором у вас был бы класс, который по крайней мере не был бы basic_istreamили basic_ostream. Есть один?

спенсер
источник

Ответы:

1

Другая причина, по которой класс имеет открытый конструктор, заключается в том, чтобы эта сигнатура конструктора была доступна для создания производного объекта:

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

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

    public:
    A(void*);
    };

 A a(10);

Конструктор должен быть общедоступным в базовом классе, потому что объявление использования базового конструктора не изменяет доступность унаследованного конструктора.

Олив
источник
2
Кажется резонным, кроме afaik, basic_iosctor take a basic_streambuf*был публичным еще до того, как вы смогли это сделать using B::B;. Я ожидаю, что в старых реализациях был прокси-ctor: A(int x) : B(x) {}- который работает нормально, даже если Bctor есть protected.
Тед Люнгмо
0

То , что я не заметил, что std::basic_istream, std::basic_ostreamа std::basic_iostreamтакже были общественные конструкторы (каждый берет std::basic_streambuf*).

Это позволяет использовать универсальный программный аналог полиморфизма в том же духе, что и pimpl.

Таким образом, вы можете создать специализированный тип streambuf и использовать его в basic_[io], streamне создавая специализированных потоковых классов. (Функциональность ограничена: вы не можете назначить новый буфер тому же потоку, и вы должны внешне отслеживать время жизни буфера и его владельца).

Каждый из специализированных basic_[io] fstreamи basic_[io] stringstreamсодержит полный экземпляр соответствующего типа буфера. Это означает, что экземпляр специализированного типа потока будет работать только со своим внутренним буфером, а не с другим, даже не с одним и тем же типом. Использование необработанного basic_[io] stream- это (неуклюжий) обходной путь для этого.

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";
спенсер
источник