Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602

Внутреннее устройство потоков

29.09.2015, 04:23. Показов 2680. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Очень тупой вопрос - почему std::ios хранит в своих потрохах указатель на объект std::streambuf, а не является потомком std::streambuf? Принимая во внимание что std::streambuf все равно собран на виртуальных функциях, а значит поведение std::ios один фиг в итоге задается через перегрузку этих самых виртуальных функций.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.09.2015, 04:23
Ответы с готовыми решениями:

Внутреннее устройство многомерного массива и неявное преобразование массива в указатель
Букв получилось многовато. Поэтому, чтобы сэкономить Ваше время, предлагаю сразу вопрос: Буду очень благодарен, если кто-то сможет...

Внутреннее устройство
Подскажите пожалуйста где можно почитать про внутренее устройство .net c# имеется ввиду как реализованый разные коллекции/типы, linq, как...

Внутреннее устройство микроконтроллера
Здравствуйте ! Подскажите пожалуйста , с какой книги ( книг ) или сайта можно начать , чтобы получить ...

17
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2224 / 1426 / 420
Регистрация: 16.05.2013
Сообщений: 3,646
Записей в блоге: 6
29.09.2015, 07:44
Цитата Сообщение от Renji Посмотреть сообщение
Очень тупой вопрос - почему std::ios хранит в своих потрохах указатель на объект std::streambuf, а не является потомком std::streambuf?
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 08:02  [ТС]
Цитата Сообщение от Ilot Посмотреть сообщение
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
Но при этом эти два класса не являются самостоятельными сущностями. std::streambuf не используется нигде за пределами std::ios и его наследников, а std::ios в свою очередь не работает без std::streambuf. Я понимаю зачем разделять их на два класса, но на два объекта то какой смысл?
0
55 / 48 / 13
Регистрация: 31.10.2013
Сообщений: 166
29.09.2015, 08:44
Есть такое понятие как наследование и компазиция. Компазиция это как раз то что там есть, то есть создается объект внутри класса, а не происходит наследование. В умных книжках как раз говориться что наследование нужно использовать в крайнем случае, когда используется полиморфизм например, а так лучше использовать компазицию.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 08:47  [ТС]
Цитата Сообщение от ShadowFirst Посмотреть сообщение
В умных книжках как раз говориться что наследование нужно использовать в крайнем случае, когда используется полиморфизм например, а так лучше использовать компазицию.
Дык в std::streambuf полиморфизм и используется. Он работает только через перегруженные потомком методы.
Цитата Сообщение от ShadowFirst Посмотреть сообщение
Компазиция это как раз то что там есть, то есть создается объект внутри класса, а не происходит наследование.
Не создается он. Объект std::streambuf (вернее, его потомок) должен создавать потомок, а потом передавать std::ios. И вот зачем такой изврат - я понять не могу.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.09.2015, 09:05
Цитата Сообщение от Renji Посмотреть сообщение
Но при этом эти два класса не являются самостоятельными сущностями.
на самом деле вполне себе самостоятельные.
к тому же решают различные задачи.

посмотрите внимательно на этот пример:
http://www.cplusplus.com/reference/ios/ios/rdbuf/

представьте себе, что std::ios - это магнитофон.
магнитофоны бывают разные.
они по разному воспроизводят получаемые данные.

а std::streambuf - устройство, которое непосредственно работает
с физическим источником данных:
кассеты, пластинки, копакт диски.
назовем его "стриммером".

любые stl-compatible магнитофоны умеют
с любыми stl-compatible стриммерами.
благодаря стандартизированному интерфейсу.

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

таким образом, получается, что std::streambuf определяет,
как прочитать байтики из источника.
а std::ios определяет, как эти байтики интерпритировать.

пример:
можно подсунуть std::streambuf в корпус zipstream, и поиметь зазипованный архив так же просто,
как и обычный текстовый/бинарный файл.

можно подсунуть какой нибудь замороченный custom::streambuf в обычный std::cout,
и вывести в консольку данные с како нибудь сильно замороченного носителя.
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2224 / 1426 / 420
Регистрация: 16.05.2013
Сообщений: 3,646
Записей в блоге: 6
29.09.2015, 09:08
Цитата Сообщение от Renji Посмотреть сообщение
Но при этом эти два класса не являются самостоятельными сущностями. std::streambuf не используется нигде за пределами std::ios и его наследников, а std::ios в свою очередь не работает без std::streambuf. Я понимаю зачем разделять их на два класса, но на два объекта то какой смысл?
Пример паттерна "мост". Разделение интерфейса и реализации. Чтение/запись для разных устройств на разных платформах разный. Подобное разделение позволяет писать код вне зависимости от устройства/платформы.
Тем более, что и обязанности у них разные:
Цитата Сообщение от Ilot Посмотреть сообщение
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 09:59  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
посмотрите внимательно на этот пример:
Посмотрел. Пример переопределяет поведение глобальной переменной cout. Нужно это только потому что программист не может поменять объявление этой глобальной переменной. И таких переменных в стандартной библиотеке целых три - cout, cin, cerr. Вся свистопляска ради трех переменных что ли?
Цитата Сообщение от hoggy Посмотреть сообщение
можно подсунуть какой нибудь замороченный custom::streambuf в обычный std::cout,
и вывести в консольку данные с како нибудь сильно замороченного носителя.
А можно тупо объявить глобальную переменную custom::iostream my_cout. Но понимаю, код прибит к cout гвоздями.
Цитата Сообщение от Ilot Посмотреть сообщение
Пример паттерна "мост". Разделение интерфейса и реализации. Чтение/запись для разных устройств на разных платформах разный. Подобное разделение позволяет писать код вне зависимости от устройства/платформы.
Кросс-платформенная функция пишет через std::ostream&stream (дальний потомок std::ios). Объясните тупому на пальцах какая функции разница, есть внутри std::ostream паттерн "мост" или нет (ссылка std::ostream& скушает любых потомков std::ostream, с любыми перегрузками методов).
0
Эксперт по математике/физикеЭксперт С++
 Аватар для Ilot
2224 / 1426 / 420
Регистрация: 16.05.2013
Сообщений: 3,646
Записей в блоге: 6
29.09.2015, 10:18
Цитата Сообщение от Renji Посмотреть сообщение
Кросс-платформенная функция пишет через std::ostream&stream (дальний потомок std::ios).
Было же написанно и неоднократно std::ios не пишет/читает из устройства. Наследники этого класса управляют форматированием, а запись/чтение делегируют буферу. Можно прямо работать с буфером минуя потоки.
Цитата Сообщение от Renji Посмотреть сообщение
Объясните тупому на пальцах какая функции разница, есть внутри std::ostream паттерн "мост" или нет (ссылка std::ostream& скушает любых потомков std::ostream, с любыми перегрузками методов).
Все верно. Так и задумывалось. Т.е. создать интерфейс для однообразной работы с разными устройствами. Но так как потоки переехали из распространенной в то время библиотеки ввода/вывода то вопросы следует задавать ее разработчикам.
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 10:19  [ТС]
Цитата Сообщение от Ilot Посмотреть сообщение
Но так как потоки переехали из распространенной в то время библиотеки ввода/вывода то вопросы следует задавать ее разработчикам.
А, то есть такая архитектура по наследству досталась. Это уже понятнее, спасибо.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.09.2015, 13:51
Цитата Сообщение от Renji Посмотреть сообщение
Вся свистопляска ради трех переменных что ли?
ради возможности цеплять к уже существующим механизмам любые источники данных,
и любые преобразователи этих данных.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 19:41  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
ради возможности цеплять к уже существующим механизмам любые источники данных,
и любые преобразователи этих данных.
Эта возможность есть и при наследовании std::ios от streambuf.
C++
1
2
3
4
5
6
7
8
class my_stream:public std::istream,std::streambuf
{
public:
    //ну вот какая нафиг разница, написано здесь istream(this) или istream(new my_streambuf())?
    my_stream():istream((std::streambuf*)this){}
private:
    //реализация моего собственного std::streambuf
};
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.09.2015, 19:58
Цитата Сообщение от Renji Посмотреть сообщение
Эта возможность есть и при наследовании std::ios от streambuf.
есть особое устройство, которое стандартный streambuf не поддерживает.

я хочу вывести данные в консоль.
(или на диск, или в зип, или в базу данных, это не принципиально).
из нового носителя данных.

зачем мне велосипедить стандартный стрим,
если достаточно завелосипедить только наследника std::streambuf,
а весь остальной код останется без изменений?
зачем велосипедить, если можно по максимуму использовать stl ?

так реализуется идеома "закрыт для изменений, открыт для расширений".
весь уже написанный и протестированный код остается без изменений.
функционал наращивается, но старый не изменяется.

конечно, в суровой реальности все не так безоблачно прекрасно.
но в целом эта идея работает.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 20:13  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
зачем мне велосипедить стандартный стрим,
если достаточно завелосипедить только наследника std::streambuf,
а весь остальной код останется без изменений?
Ткните пальцем, где в моем примере с наследованием, меняется код не относящийся к streambuf.
C++
1
2
3
4
5
6
7
8
9
10
11
12
class bicycle_stream:std::ostream,std::streambuf
{
public:
    bicycle_stream():ostream(this){}
private:
    //реализация интерфейса streambuf
    streamsize xsputn (const char* s, streamsize n){
        for(;n;--n)
            cout<<*s++;
    }
    //реализация своего интерфейса ostream. Ровно ноль строк
};
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.09.2015, 20:19
Цитата Сообщение от Renji Посмотреть сообщение
Ткните пальцем, где в моем примере с наследованием, меняется код не относящийся к streambuf.
выше я приводил вам пример подмены стриммера.

приведите мне аналогичный пример.

с использованием вашего подхода.

требуются преобразования:

zipstream <---> ostream, fstream.

наследник streambuf читает видеопоток,
и распознает особые маркеры среди потока байтиков,


то есть не обязательно писать код алгоритмов.
интересует архитектурное решение.

ваш bicycle_stream сейчас нарушают идеому
"закрыт для изменений, открыт для расширений".

нужно знать про какой то bicycle_stream,
что бы записать данные на диск?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 20:26  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
приведите мне аналогичный пример.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void any_stream_print(std::ostream&stream,const char*str)
{
    stream<<"Мы принимаем любых потомков ostream! Вы хотели напечатать: "<<str;
}
int main()
{
    zipstream zstream;
    bicycle_stream bstream;
    any_stream_print(cout,"Это cout");
    any_stream_print(zstream,"Это zstream");
    any_stream_print(bstream,"Это велосипед");
    return 0;
}
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
29.09.2015, 20:29
Цитата Сообщение от Renji Посмотреть сообщение
stream<<"Мы принимаем любых потомков ostream! Вы хотели напечатать: "<<str;
у меня в исходном коде фигурирует:

C++
1
os << data; // os - ostream
мне теперь код переписывать придется?
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
29.09.2015, 21:21  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
у меня в исходном коде фигурирует:
А у меня фигурирует:
C++
1
2
3
is.seekg(save_pos);
getline(is,line);
throw std::runtime_error("Can't parse \""+line+"\"");
Теперь дописываем к этому делу is.rdbuf(cin.rdbuf()) и программа падает. Потому как cin никаких seekg скорее всего не поддерживает.
Цитата Сообщение от hoggy Посмотреть сообщение
мне теперь код переписывать придется?
Конечно. Программа должна быть изначально рассчитана на работу с произвольным потоком. В документации должно быть изначально подписано что этот поток должен поддерживать. Иначе попытки заменить один поток другим будут иметь непредсказуемые последствия. Если же программа уже рассчитана на поддержку произвольных потоков, то и rdbuf костыль ей без надобности.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.09.2015, 21:21
Помогаю со студенческими работами здесь

Внутреннее устройство объекта jQuery
Добрый день, Разбираясь с jQuery возникли вопросы по внутреннему устройству объекта, который возвращает главная функция $(). ...

Внутреннее устройство приведения типов
Как происходит, например, повышающее приведение типов (от типа-потомка к типу-родителю)? Что происходит с теми полями, методами,...

Внутреннее устройство промышленного роутера
Всем доброго времени суток! Может ли кто подсказать, из чего состоит ПРОМЫШЛЕННЫЙ роутер? Всем заранее спасибо!

Посмотреть внутреннее устройство системных функций
Есть ли возможность посмотреть исходный код некоторых встроенных классов. Конкретно интересует public class Uri

Как получить устройство, к которому приатачено ваше устройство в стеке устройств
Пишу минипорт драйвер для usb аудио устройства. Для создания устройства вызывается функция порт драйвера PcAddAdapterDevice, в ней...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru