Почему у 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";