![]() |
|
Модераторы: bsa |
![]()
|
|
| kemiisto |
|
||||||||||||||||||||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
"Мы начинаем КВН!" (с) ==================================================================== Часть I. Классы_с_точки_зрения_C++. Пролог. Когда в какой-нибудь книге или статье речь заходит о классах, сразу же "всплывает" нехорошая аббревиатура ООП с ещё кучкой нехороших слов (инкапсуляция, наследование, полиморфизм, ...). Объектно-ориентированное программирование (ООП) мы оставим "на потом". Сейчас лишь скажем, что в своё время оно появилось как ещё один способ борьбы со всё возраставшей (и по сей день возрастающей) сложностью программного обеспечения. Стоит упомянуть, что структурное программирование - так же способ борьбу со сложностью ПО. Хорошо структурированные программы остаются читабельными и сопровождаемыми при объёме на порядок большем, чем программы плохо структурированные. Про неструктурированные программы и говорит нечего. Спагетти-код такой спагетти. Давайте поговорим об этой самой борьбе со сложностью, а к ООП вернёмся, но потом. В конце концов, ООП - всего лишь частный приём борьбы со сложностью, да и к тому же domain specific (имеет отношение только к программированию). Итак, сложность и борьба с нею посредством абстрагирования - центральная тема пролога. Поехали! Самый действенный способ борьбы со сложностью - вушеупомянутое абстрагирование. Позволю себе процитировать свой любимый учебник философии за авторством Алексеева П.В., Панина А.В.
Добавить тут нечего. Разве вот что. Абстрагирование помогает не только лучше понять предмет/явление, но и лучше его описать (что, конечно же, является следствием глубокого понимания). В конце концов наша конечная цель именно описание предмета/явления для сохранения полученных знаний и передачи благодарным потомкам. Итак, казалось бы, причём тут абстрагирование? Давайте посмотрим, как его использовать в программировании. Три стека. У нас возникла потребность в стеке целых чисел. Что это можно почитать в той же Википедии. Итак, если мы абстрагируемся от конкретной задачи (которую я и не сформулировал, кстати говоря), абстрагируемся от типа данных элементов стека (целое число) и ещё много от чего, мы придём к выводу, что наш стек (чем бы он ни был) поддерживал как минимум 2 операции:
Остальное - по вкусу. Существует несолько вариантов реализации стека. Давайте выберем самую простенькую - реализацию на основе массива (array implementation) и напишем уже наконец-то хоть какой-то код! Вариант №1. Абстрактная структура данных. stack_ads.h
stack_ads.cpp
main.cpp
Что тут есть что? Так, суффик ads - аббревиатура от abstract data structure (ADS). Абстрактная структура данных. Абстрактна она по нескольким причинам.
Стоп! Один программист, другой программист... Брррр.... Так вас что, двое!? Вот тут весь "цимус". Программистов, работающих над одним проектом может быть не только двое-трое. Тысячи их!!! Даже если программист и один, часть кода может быть написана сейчас, часть - через месяц, и, строго говоря, это уже два разных человека, не то что программиста. В одну реку, как говорится, дважды не войдешь. Вот где важность абстрагирования в плане разделения на интерфейс и реализацию трудно переоценить. Вот где абстрагирование, как сокрытие информации, простите, "рулит". И вот почему. Удобно думать обо всём это в терминах клиентского и серверного модуля. [наброс]Вот только модулей в С++ нет! Я как то уже писал об этом, оказывается. Эх там была красивая картинка. В общем, два модуля (клиент и сервер) прямоугольничками. И от сервера к клиенту треугольничек шёл. Этот треугольничек - наш интерфейс. "Бутылочное горлышко" если хотите, через которое серверный модуль общается с внешним миром. А сам серверный модуль - бутылка из непрозрачного стекла, "чёрный ящик". Так вот существует даже такая методология разработки ПО - design by contract. Нарошно не привожу русскоязычный термин. Не нравиться мне "контрактное программирование". Уж лучше программирование по контракту. Если отбросить вопросы верификации, то контракт - это соглашение между программистами по поводу интерфейсов. Как только такое соглашение достигнуто и интерфейсы специфицированы, каждый независимый модуль может писать отдельно взятый программист. И сколь бы не была сложна и объёмна задача, программу всегда можно разделить на независимые модули, которые в конце объединить и получить программный продукт. Divide et impera, %username%! Вариант №2. Абстрактный тип данных. Реализация через struct в C-стиле. Но Вернёмя к нашим баранам нашему коду. У первой версии серверного модуля есть (как минимум) один большой недостаток - больше одного стека использовать в клиентском коде не получится. Устраняем. stack_adt.h
stack_adt.cpp
main.cpp
Что мы тут изменили? Теперь наш серверный модуль предоставляет клиентскому самый настоящий асбстрактный тип данных, abstract data type (ADT). Всё вышеописанное по поводу абстрагирования верно и в этом случае. Преимущества теже + получаем возможность иметь более одной абстрактной структуры данных. Каждая абстрактная структура данных есть елемент множества, которое описывается абстрактным типом данных. Вариант №3. Абстрактная структура данных. Реализация через класс. То были цветочки, а теперь, будьте любезны, ягодки. В смысле, классы. Stack.h
Stack.cpp
main.cpp
Та-да! Всё тот же АТД мы представили теперь классом. А есть ли разница? Ну, что видно невооружённым взглядом:
Эпилог. А вот теперь подумаем: стоила ли игра свеч? Перечисленные преимущества, мягко говоря, сомнительны. Ну подумаешь, немного другой синтаксис. Но будут "плюшки"! Первую "плюшку" в примере с классами я уже показал. Может и зря. Это конструктор, который инициализирует один из членов класса. Обращаю внимание, что в С++ всё тоже самое можно сделать и со struct. Последний пример можно вообще переписать заменив class на struct. Воспринимайте второй пример (ATD "через" struct) как написанный на обычном С, а не на С++. Но это так "плюшечка". А настоящие "плюшки" пойдут во второй части. ООП - эта такая большая корзинка с плюшками. Пахнет вкусно, но не сейчас. P.S. Бета-версия. Должны быть опечатки, описки, неточности, ошибки. Ребята, кто в С++/С больше моего соображает, посмотрите код внимательно. Это сообщение отредактировал(а) kemiisto - 15.4.2010, 16:53 -------------------- |
||||||||||||||||||||
|
|||||||||||||||||||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
Перечитал. Надо вычищать и расширать.
А может первые 2 примера на plain C "вкорячить", а не на ++? Хотя... -------------------- |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
kemiisto, ooo.. это что эпидемия ?!
ну а если серьезно, то похвально.. к коду пока не приглядывался, но откуда взялся static ?! ну и критика статьи : имхо не стоит уделять время, и место для публикации реализации, достаточно освещать только интерфейс, ну и лишь некоторые моменты реализации, заслуживающие отдельного внимания.. кстати в этим будет еще раз показан смысл АТД - есть интерфейс и понятно как с ним работать, а какая там реализация клиенту даже задумаваться не надо. Это сообщение отредактировал(а) mes - 15.4.2010, 13:52 |
|||
|
||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
От балды. Я почитал - нельзя никак. Ну кроме как явно для каждой переменной. static - от балды, компилятор "подсказал". -------------------- |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
||||
|
||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
Да я понял уже. И ведь сказал же - мне не интересно слушать, что это ошибка. Я хочу видеть решение. -------------------- |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
||||
|
||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
Да, логично. Бывает. -------------------- |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
также если следовать правилам хорошего тона, то у стека должен быть метод top() для доступа к верхнему значению..
имхо, не очень удачное название.. лучше приучать читателя сразу к общепринятым (по крайней мере для С++) наименованиям.. Добавлено @ 14:55
А вот тут я не понял к какому выводу подталкивают читателя... Те "преимущества" представленные перед цитатой, это лишь следствия выбранного способа реализации классов. Ну а основное, ради чего ввели классы, должно будет представлено во второй части статьи : Это сообщение отредактировал(а) mes - 15.4.2010, 14:56 |
|||
|
||||
| kemiisto |
|
||||||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
Разве? По-моему нужен только push()/pop(). Остальное - опционально. Я уж и так тут добавил. Ладно, подумаю.
Ну можно... size()? Как это не поняли, если дальше и написали:
Это сообщение отредактировал(а) kemiisto - 15.4.2010, 15:09 -------------------- |
||||||
|
|||||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
Дело в том, что обсуждаемая цитата хотя в общем контексте и понятна и "безопасна", но, мне показалось, несет скрытый подтекст.. хотя может просто сказалось выработанная привычка ожидать от Вас подвоха в сторону С++ |
|||
|
||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
-------------------- |
|||
|
||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 85 Всего: 196 |
ну развели тут, понимаешь ли...
Ладно. продолжайте, если в итоге что-то хорошее выйдет, можно будет в ФАК засунуть. |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 79 Всего: 250 |
это не отражено в коде.. хотя и не знаю надо ли.. в общем предлагаю для лучшего абстрагитования затайпдефить int к stack_value_t или просто к Т. Это сообщение отредактировал(а) mes - 15.4.2010, 19:38 |
|||
|
||||
| kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 5 Всего: 160 |
Кому дадено, тот увидит. В парочке мест заменить int на another_type - не проблема. -------------------- |
|||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |