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

std::basic_iosимеет публичный конструктор:

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

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

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

2 ответа

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

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

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

    public:
    A(void*);
    };

 A a(10);

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

Я не заметил, что 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";
Другие вопросы по тегам