![]() |
Модераторы: 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. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |