Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
#1

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

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

Очень тупой вопрос - почему std::ios хранит в своих потрохах указатель на объект std::streambuf, а не является потомком std::streambuf? Принимая во внимание что std::streambuf все равно собран на виртуальных функциях, а значит поведение std::ios один фиг в итоге задается через перегрузку этих самых виртуальных функций.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.09.2015, 04:23
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Внутреннее устройство потоков (C++):

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

Создание и завершение процессов и потоков. Приоритеты выполнения потоков - C++
Здравствуйте. Буду очень раз если поможете понять,что конкретно нужно сделать в вот этом задании,пока особого представления о...

Внутреннее представление числа в памяти - C++
нужно сделать реализацию числа в памятиfloat d1 = 72.9e-8;... а как??? это нужно число перевести в двоичную систему, или как???

Внутреннее представление конструтора и деструктора - C++
Я знаю, что конструктор и деструктор в явном виде ничего не возвращает. Однако на уровне ассемблерных команд он восстанавливает...

Внутреннее хранение данных для обработки - C++
Привет! Снова вопрос больше теоретический. Начал писать консольную программу на C++ для расчёта стоимости проезда. Например,...

Перевод десятичного числа во внутреннее представление - C++
Всем привет. Сделал программу перевода десятичного числа во внутреннее представление. Число лежит в диапазоне от -128 до 127 (тип char)....

17
Ilot
Модератор
Эксперт С++
1823 / 1181 / 232
Регистрация: 16.05.2013
Сообщений: 3,118
Записей в блоге: 5
Завершенные тесты: 1
29.09.2015, 07:44 #2
Цитата Сообщение от Renji Посмотреть сообщение
Очень тупой вопрос - почему std::ios хранит в своих потрохах указатель на объект std::streambuf, а не является потомком std::streambuf?
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
0
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 08:02  [ТС] #3
Цитата Сообщение от Ilot Посмотреть сообщение
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
Но при этом эти два класса не являются самостоятельными сущностями. std::streambuf не используется нигде за пределами std::ios и его наследников, а std::ios в свою очередь не работает без std::streambuf. Я понимаю зачем разделять их на два класса, но на два объекта то какой смысл?
0
ShadowFirst
55 / 48 / 1
Регистрация: 31.10.2013
Сообщений: 161
29.09.2015, 08:44 #4
Есть такое понятие как наследование и компазиция. Компазиция это как раз то что там есть, то есть создается объект внутри класса, а не происходит наследование. В умных книжках как раз говориться что наследование нужно использовать в крайнем случае, когда используется полиморфизм например, а так лучше использовать компазицию.
0
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 08:47  [ТС] #5
Цитата Сообщение от ShadowFirst Посмотреть сообщение
В умных книжках как раз говориться что наследование нужно использовать в крайнем случае, когда используется полиморфизм например, а так лучше использовать компазицию.
Дык в std::streambuf полиморфизм и используется. Он работает только через перегруженные потомком методы.
Цитата Сообщение от ShadowFirst Посмотреть сообщение
Компазиция это как раз то что там есть, то есть создается объект внутри класса, а не происходит наследование.
Не создается он. Объект std::streambuf (вернее, его потомок) должен создавать потомок, а потом передавать std::ios. И вот зачем такой изврат - я понять не могу.
0
hoggy
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
29.09.2015, 09:05 #6
Цитата Сообщение от 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
Модератор
Эксперт С++
1823 / 1181 / 232
Регистрация: 16.05.2013
Сообщений: 3,118
Записей в блоге: 5
Завершенные тесты: 1
29.09.2015, 09:08 #7
Цитата Сообщение от Renji Посмотреть сообщение
Но при этом эти два класса не являются самостоятельными сущностями. std::streambuf не используется нигде за пределами std::ios и его наследников, а std::ios в свою очередь не работает без std::streambuf. Я понимаю зачем разделять их на два класса, но на два объекта то какой смысл?
Пример паттерна "мост". Разделение интерфейса и реализации. Чтение/запись для разных устройств на разных платформах разный. Подобное разделение позволяет писать код вне зависимости от устройства/платформы.
Тем более, что и обязанности у них разные:
Цитата Сообщение от Ilot Посмотреть сообщение
Потому что назначение std::ios выполнять форматирование ввода/вывода, а std::streambuf читать/писать из/в устройства.
0
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 09:59  [ТС] #8
Цитата Сообщение от 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
Модератор
Эксперт С++
1823 / 1181 / 232
Регистрация: 16.05.2013
Сообщений: 3,118
Записей в блоге: 5
Завершенные тесты: 1
29.09.2015, 10:18 #9
Цитата Сообщение от Renji Посмотреть сообщение
Кросс-платформенная функция пишет через std::ostream&stream (дальний потомок std::ios).
Было же написанно и неоднократно std::ios не пишет/читает из устройства. Наследники этого класса управляют форматированием, а запись/чтение делегируют буферу. Можно прямо работать с буфером минуя потоки.
Цитата Сообщение от Renji Посмотреть сообщение
Объясните тупому на пальцах какая функции разница, есть внутри std::ostream паттерн "мост" или нет (ссылка std::ostream& скушает любых потомков std::ostream, с любыми перегрузками методов).
Все верно. Так и задумывалось. Т.е. создать интерфейс для однообразной работы с разными устройствами. Но так как потоки переехали из распространенной в то время библиотеки ввода/вывода то вопросы следует задавать ее разработчикам.
1
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 10:19  [ТС] #10
Цитата Сообщение от Ilot Посмотреть сообщение
Но так как потоки переехали из распространенной в то время библиотеки ввода/вывода то вопросы следует задавать ее разработчикам.
А, то есть такая архитектура по наследству досталась. Это уже понятнее, спасибо.
0
hoggy
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
29.09.2015, 13:51 #11
Цитата Сообщение от Renji Посмотреть сообщение
Вся свистопляска ради трех переменных что ли?
ради возможности цеплять к уже существующим механизмам любые источники данных,
и любые преобразователи этих данных.
0
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 19:41  [ТС] #12
Цитата Сообщение от 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
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
29.09.2015, 19:58 #13
Цитата Сообщение от Renji Посмотреть сообщение
Эта возможность есть и при наследовании std::ios от streambuf.
есть особое устройство, которое стандартный streambuf не поддерживает.

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

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

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

конечно, в суровой реальности все не так безоблачно прекрасно.
но в целом эта идея работает.
0
Renji
2000 / 1368 / 308
Регистрация: 05.06.2014
Сообщений: 3,901
29.09.2015, 20:13  [ТС] #14
Цитата Сообщение от 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
6701 / 2883 / 494
Регистрация: 15.11.2014
Сообщений: 6,480
Завершенные тесты: 1
29.09.2015, 20:19 #15
Цитата Сообщение от Renji Посмотреть сообщение
Ткните пальцем, где в моем примере с наследованием, меняется код не относящийся к streambuf.
выше я приводил вам пример подмены стриммера.

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

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

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

zipstream <---> ostream, fstream.

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


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

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

нужно знать про какой то bicycle_stream,
что бы записать данные на диск?
0
29.09.2015, 20:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
29.09.2015, 20:19
Привет! Вот еще темы с ответами:

Внутреннее (машинное) представление данных двух типов - C++
Разработать программу, которая выводит на экран внутреннее (машинное) представление данных двух типов:short int и long double. Обеспечить...

Внутреннее представление типа Double через Long - C++
Привет. Для оптимизации работы одного вычислительного алгоритма потребовалось найти некое биективное отображение Double &lt;-&gt; Long для...

Перевод даты из символьного формата во внутреннее представление и обратно - C++
Разработать функцию, которая переводит дату из символьного формата «дд.мм.гггг» во внутреннее представление и обратно.Только чтобы не...

Программа показывающая внутреннее двоичное представление типа данных - C++
Необходимо показать внутреннее двоичное представление типа данных, используя операции сдвига(&lt;&lt;,&gt;&gt;) и поразрядные логические операции...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru