| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > классы |
| Автор: 555shiro 14.4.2010, 18:25 |
| здравствуйте! подскажите пожалуйста где можно найти и изучить самую простенькую программу на "Классы" в качестве примера ? вообщем чем больше тем лучше! поискал в инете ничего путного не нашёл =( |
| Автор: ИванМ 14.4.2010, 18:33 | ||
555shiro, на этом форуме |
| Автор: azesmcar 14.4.2010, 20:07 | ||||||||||||||||||||||
| Классы - это наверное самая сложная часть C++ для новичков после указателей. Не потому что сложно понять как они работают, а сложно понять зачем они нужны. Большинство программ с использованием ООП у новичков (да и у не новичков тоже) сводятся к написанию функций в классах. Ну и какой смысл в такой программе? Чем такой способ программирования отличается от процедурного? Ничем! Очень важно понять саму концепцию ООП и тогда использование классов в программе облегчит вашу задачу. Глубокие понимание ООП придет с изучением шаблонов проектирования, но до этого еще есть время. Начнем с простого понятия класс. Вспомним понятие структуры из языка Си; по сути это объявление нового типа, который состоит из набора объектов определенных типов, например нам нужен тип, хранящих координаты.
и еще один тип, хранящий информацию о линии. Для линии нам понадобится координаты двух точек, используем уже существующую структуру Point
теперь нам нужна функция, чтобы подсчитать длину этой линии
теперь представим тоже самое в виде класса, т.е. напишем не глобальную функцию а member функцию
в использовании изменилось не многое, но мы теперь представили нашу линию как самостоятельный объект, который умеет считать свою длину. Можем также создать классы типа Rectangle (прямоугольник), Circle (круг) ... и добавить в них свои функции, например подсчета площади. В таком виде классы не почти не отличаются от структур, хотя на самом деле в C++ класс от структуры отличается одним маленьким нюансом, но об этом потом. 3 главные парадигмы объектно-ориентированного программирования - это
Инкапсуляция дает возможность скрывать детали реализации от пользователей вашего класса, предоставляя ему удобный интерфейс для работы с объектом, но скрывая то, что его не касается, например в этом примере
объекты start и end объявлены как private, это значит, что к этим объектам может обратится только функции самого класса и друзья класса. public означает, что доступ открыт для всех protected открывает доступ только для наследников класса и его друзей например у нас есть функция, которая нужна для внутренней реализации функционала нашего класса и пользователям предоставлять доступ к ней нельзя, в таком случае она объявляется как private, дабы уберечь пользователя от случайных ошибок. Наследование позволяет расширить функционал класса, не меняя основной, например у нас есть класс TV (телевизор) который работает, имеет функции On(), Off() и ChangeChannel(), но мы хотим создать новый, революционный телевизор под маркой CoolTV, который имеет функцию блокирования каналов, в таком случае мы наследуем уже имеющуюся технологию телевизора, с его функционалом (чтобы не изобретать велосипед) и расширяем его.
тогда наш класс CoolTV будет обладать всеми функциями класса TV плюс функцией блокирования канала. Полиморфизм (динамический) позволяет динамически определять функцию, которая должна быть вызвана на основе типа объекта. Допустим у нас в классе TV есть функция show(), которая отвечает за показ изображения и нам хочется в нашей новой, современной модели изменить эту функцию так, чтобы она показывала цветное изображение.
переопределяем функцию show(), посмотрим что получилось
если мы вызываем функцию show() через указатель базового класса, вызывается функция из базового, несмотря на то, что на самом деле создан класс CoolTV (т.е. наследник). В чем же проблема? Допустим у нас есть класса RemoteControl, который уже работает с классом TV
при включении нажатии на кнопку включения (т.е. вызове функции On() из класса RemoteControl) вызывается функция On() телевизора и функция show(). В вышеупомянутом примере мы не сможем использовать наш пульт ДУ для класса телевизора CoolTV, потому что несмотря на то, что мы написали функцию вывода цветного изображения эта функция не вызывается. Это очень легко исправить и именно этим и занимается полиморфизм.
достаточно добавить ключевое слово virtual перед определением функции в базовом классе, после этого программа начнет вести себя следующим образом
и тогда нам не придется создавать еще один пульт дистанционного управления для работы с нашим цветным телевизором. Тема очень большая и все тут написать нереально, вот это то, что не поленился описать, все равно часто спрашивают, буду посылать всех сюда Может потом еще добавлю, надеюсь нигде не ошибся, много текста а я слишком ленивый, чтобы все проверять еще раз |
| Автор: azesmcar 14.4.2010, 20:51 | ||
Исправил. |
| Автор: mes 14.4.2010, 20:54 |
структура не хранит типы.. структура, как объект, состоит из набора объектов каких-то типов.. ну а как тип, описывает это устройство. P.S. сорри за придирки, я из хороших побуждений.. P.S.S. на какую статью решился ! |
| Автор: azesmcar 14.4.2010, 21:09 | ||||
Ну нет опыта написания книг, могу термины попутать
дополняйте, исправляйте..я отредактирую, у меня нет претензий на идеал, за пол часика полностью отточить не удастся, иначе быть мне писателем а не программистом |
| Автор: kemiisto 14.4.2010, 21:13 |
Я даже могу подсказать в каком направлении работать:
Побочные эффекты: уже на стадии осмысления будут весьма и весьма вероятны рефлекторные сокращения ЖКТ даже при беглом взгляде на C++. Опережая вопрос "Что сам не напишешь?", скажу сразу: я - на стадии осмысления. P.S. "Ходят слухи", что для полного просветления можно "курнуть" ФП и осознать единство парадигм функционального и объектно-ориентированного программирования. P.P.S. Ещё можно "курнуть" Lua. Понять, что ООП бывает и без классов. Нужны то всего first-class functions и таблички. |
| Автор: azesmcar 14.4.2010, 21:14 | ||
| kemiisto Мы тут вроде о C++ говорим. Добавлено через 1 минуту и 12 секунд
и вообще-то вопрос был о КЛАССАХ. |
| Автор: kemiisto 14.4.2010, 21:20 |
Вижу, вижу. Да, и вот начало твоего ответа: |
| Автор: mes 14.4.2010, 21:33 | ||||
P.S.
слово "единство " имхо не очень подходит на эту роль.. правда другого подходящего вспомнить также не могу |
| Автор: kemiisto 14.4.2010, 21:36 | ||
Во-первых, я забыл последний пункт списка:
Во-вторых, ещё раз процитирую: Объясняющему это важно понять в первую очередь. Ничего личного! |
| Автор: ИванМ 14.4.2010, 21:40 |
| Такое ощущение что перед тем, как отправить свой пост, kemiisto курил не только Smalltalk, Oberon-2/Component Pascal, ФП и Lua, а что-то еще |
| Автор: mes 14.4.2010, 21:42 | ||
ну это к обсуждаемому напрямую не относится.. имхо, имелось ввиду : Очень важно понять саму концепцию ООП_с_точки_зрения_C++ и у автора была поправка на этот счет : Добавлено @ 21:44
Ну тогда придется предположить, что он курит это "что-то" чуть ли не постоянно даже беглый просмотр высказываний "прошлых лет" поможет убедиться в этом.. |
| Автор: mes 14.4.2010, 21:57 |
| А вообще он просто за мир во всем мире, и ему обидно, что программисты как художники, используют не радужную палетту с ограниченным набором красок, изготовленную специально для удобства человека, а неподъемный набор красок и кисточек на любой вкус.. |
| Автор: kemiisto 14.4.2010, 22:08 |
Тут много мыслей будет. Во-первых, все беды С++ вот от этого. Строгая_с_точки_зрения_C++ типизация, обобщённое_с_точки_зрения_C++ программирование, уже упомянутое ООП_с_точки_зрения_C++ и многое-многое другое. Это доставляет, ей богу. Во-вторых, концепция, она на то и концепция (парадигма такая парадигма, если хотите) чтоб быть "language agnostic". Суть вот в чём. Существует достаточно распространённая точка зрения, что чем больше языков изучил программист, тем лучше. Изучил, скажем только С++, многие концепции остались незатронутыми совсем, а затронутые могут быть совершенно неверно истолкованы. Поэтому неплохо изучить Java/C#, сверху "прикрыть" Питоном. Ну и там целая плеяда Ruby, Objective-C, D, ... - по вкусу. И может создаться впечатление, что я советую что-то подобное и с посылом согласен. Впечатление, смею заверить, обманчивое. Дело в том, что необходимость в изучении всей этой (не побоюсь этого слова) кучи только одна - попытка невелировать идиотизмы каждого конкретного языка, увидив их воучию при сравнении с "товарищами по несчастью". Все эти языки - жуткая смесь нормальных идей и бреда, родившегося в головах "творцов". Бреда обычно больше. Причём наблюдается корреляция: чем больше бреда в языке, тем больше ЧСВ у творца. Но что хорошо - бредили все по разному. И вот продираясь через "прелести" этой "могучей кучки" можно, конечно, многое для себя уяснить. Но, "мы пойдём другим путём". Надо смотреть языки концептуально чистые, простые, основанные на небольшом таком списочке идей-концепций. Ухватить суть, поставить технику. И тогда уже при взгляде на представителя кучи, будет не хорошо, но "как стекло протёрли" (с) Вот я примеры таких языков привёл. "Наводку" дал. Дальше - дело добровольное. P.S. Выдыхаю. |
| Автор: kemiisto 14.4.2010, 22:28 |
Рано. Не довёл до конца. Так вот. Эти простые языки хороши именно тем, что за деревьями синтаксиса виден лес концепций. |
| Автор: qweqwe 14.4.2010, 22:29 | ||||||
не удержался и переделал парочку примеров с плюсов на F# (на OCaml будет примерно также)
здесь даже на один конструктор больше, мечта любого плюсовода - вызвать один конструктор из другого |
| Автор: ИванМ 14.4.2010, 22:32 |
| kemiisto, а теперь, если не сложно, тоже самое только с ориентиром на практику. Как ваши идеи помогут лучше питаться и больше позволять излишеств? Добавлено через 2 минуты и 41 секунду kemiisto, о, у вас уже последователи появились |
| Автор: qweqwe 14.4.2010, 22:35 |
если вам это не понятно, то, по всей видимости вы не заслуживаете всего этого |
| Автор: mes 14.4.2010, 22:48 | ||
они позволят освободить мысли, и при програмировании не зависить от языка, а использовать его я практически полностью подерживаю kemiisto в высказанных мыслях, кроме одного.. того по какому поводу было все это высказано |
| Автор: azesmcar 14.4.2010, 22:48 |
Не помешало бы понять, что мы говорим об ООП в контексте C++ Неужели я должен был это указать находясь в самом разделе C/C++? Я вообще-то начинал писать ответ, а потом из одного следовало другое ... ну и вышла такая вот статья или называйте ее как хотите. kemiisto, ну не знаю я оберон, прости грешного (исправится не обещаю, будем считать что я неисправимый грешник)..я C++ программист Добавлено @ 22:56 ИванМ kemiisto ярый ненавистник языка C++, я тоже конечно не в восторге, у него много минусов, но что делать? за что платят на том и пишем. |
| Автор: ИванМ 14.4.2010, 22:57 | ||
| qweqwe, уж куда мне до вас (что за хамство?) azesmcar, а идея у вас была благая
все равно ничего не понял) видимо qweqwe прав) |
| Автор: limelight 14.4.2010, 23:19 | ||||||
| Исправьте, плз в куске кода
в последней строке должно быть ведь
а не
?? |
| Автор: qweqwe 14.4.2010, 23:20 |
вон из профессии! |
| Автор: ИванМ 14.4.2010, 23:27 |
| qweqwe, уже вещи собрал) |
| Автор: azesmcar 14.4.2010, 23:38 |
| kemiisto Понимаешь, вообще-то моей целью было рассказать частично о концепциях ООП в C++ и о классах и я попытался сделать это доступным образом. Если ты считаешь, что я не смог уместить в двести строк книгу GOF в вольной интерпретации то ты совершенно прав Я не рассказал и половину того, что поддерживает C++, а говорить о том, что он НЕ поддерживает было бы смешно в конкретной ситуации. Если ты считаешь что в описании того, что есть на данный момент есть ошибка то укажи, я ее с удовольствием исправлю, я и не утверждал что их нет, коды писал тут, текст тоже, даже в книгах ошибаются..мало ли, всякое случается, а если есть что дополнить то милости просим, с удовольствием почитаю. Добавлено через 3 минуты и 23 секунды limelight, да, поганый копи-паст исправил, спасибо. |
| Автор: kemiisto 15.4.2010, 08:38 |
| azesmcar, OK. Сделаем так. Сегодня до полудня (т.е. до 2 МСК) я напишу сюда первую часть опуса о классах. Чтоб не было ощущения, что я тут из пустого в порожнее... |
| Автор: azesmcar 15.4.2010, 08:48 |
| kemiisto Отлично, только у меня нет такого ощущения, я прекрасно понимаю о чем ты говоришь и даже согласен, но это как бы не имеет отношения к теме, мы говорим разном, у меня не было цели описывать то, о чем ты пишешь ну в общем ждем-с, с радостью почитаю. |
| Автор: Shaggie 15.4.2010, 09:51 | ||||
А теперь под бравурную музыку в форуме C/C++: для новичков появляется описание Haskell type classes
В скриптовых языках отчётливо видно, что все объекты являются не более чем словарями ключей и значений. Вместо Lua можно взять JavaScript. Или Perl. Или Python, в нём, правда, уже меньше заметно. А можно нарисовать полную объектность на C и осознать лишний раз, что все эти парадигмы - лишь навороты над голым ассемблером, причём, по большей части, запрещающие. Надеюсь, трава кончится раньше. Вообще в этой теме по существу только azesmcar ответил, за что ему заслуженный плюс в репутацию, остальное можно будет со временем вынести в религиозные войны (надо только ответа kemiisto дождаться). |
| Автор: kemiisto 15.4.2010, 12:12 | ||||||||||||||||||||
"Мы начинаем КВН!" (с) ==================================================================== Часть I. Классы_с_точки_зрения_C++. Пролог. Когда в какой-нибудь книге или статье речь заходит о классах, сразу же "всплывает" нехорошая аббревиатура ООП с ещё кучкой нехороших слов (инкапсуляция, наследование, полиморфизм, ...). Объектно-ориентированное программирование (ООП) мы оставим "на потом". Сейчас лишь скажем, что в своё время оно появилось как ещё один способ борьбы со всё возраставшей (и по сей день возрастающей) сложностью программного обеспечения. Стоит упомянуть, что структурное программирование - так же способ борьбу со сложностью ПО. Хорошо структурированные программы остаются читабельными и сопровождаемыми при объёме на порядок большем, чем программы плохо структурированные. Про неструктурированные программы и говорит нечего. Спагетти-код такой спагетти. Давайте поговорим об этой самой борьбе со сложностью, а к ООП вернёмся, но потом. В конце концов, ООП - всего лишь частный приём борьбы со сложностью, да и к тому же domain specific (имеет отношение только к программированию). Итак, сложность и борьба с нею посредством абстрагирования - центральная тема пролога. Поехали! Самый действенный способ борьбы со сложностью - вушеупомянутое абстрагирование. Позволю себе процитировать свой любимый учебник философии за авторством Алексеева П.В., Панина А.В.
Добавить тут нечего. Разве вот что. Абстрагирование помогает не только лучше понять предмет/явление, но и лучше его описать (что, конечно же, является следствием глубокого понимания). В конце концов наша конечная цель именно описание предмета/явления для сохранения полученных знаний и передачи благодарным потомкам. Итак, казалось бы, причём тут абстрагирование? Давайте посмотрим, как его использовать в программировании. Три стека. У нас возникла потребность в стеке целых чисел. Что это можно почитать в той же http://ru.wikipedia.org/wiki/Стек. Итак, если мы абстрагируемся от конкретной задачи (которую я и не сформулировал, кстати говоря), абстрагируемся от типа данных элементов стека (целое число) и ещё много от чего, мы придём к выводу, что наш стек (чем бы он ни был) поддерживал как минимум 2 операции:
Остальное - по вкусу. Существует несолько вариантов реализации стека. Давайте выберем самую простенькую - реализацию на основе массива (array implementation) и напишем уже наконец-то хоть какой-то код! Вариант №1. Абстрактная структура данных. stack_ads.h
stack_ads.cpp
main.cpp
Что тут есть что? Так, суффик ads - аббревиатура от abstract data structure (ADS). Абстрактная структура данных. Абстрактна она по нескольким причинам.
Стоп! Один программист, другой программист... Брррр.... Так вас что, двое!? Вот тут весь "цимус". Программистов, работающих над одним проектом может быть не только двое-трое. Тысячи их!!! Даже если программист и один, часть кода может быть написана сейчас, часть - через месяц, и, строго говоря, это уже два разных человека, не то что программиста. В одну реку, как говорится, дважды не войдешь. Вот где важность абстрагирования в плане разделения на интерфейс и реализацию трудно переоценить. Вот где абстрагирование, как сокрытие информации, простите, "рулит". И вот почему. Удобно думать обо всём это в терминах клиентского и серверного модуля. [наброс]Вот только модулей в С++ нет! Я как то уже писал об этом, http://forum.vingrad.ru/index.php?showtopic=275800&view=findpost&p=1989180. Эх там была красивая картинка. В общем, два модуля (клиент и сервер) прямоугольничками. И от сервера к клиенту треугольничек шёл. Этот треугольничек - наш интерфейс. "Бутылочное горлышко" если хотите, через которое серверный модуль общается с внешним миром. А сам серверный модуль - бутылка из непрозрачного стекла, "чёрный ящик". Так вот существует даже такая методология разработки ПО - http://ru.wikipedia.org/wiki/Контрактное_программирование. Нарошно не привожу русскоязычный термин. Не нравиться мне "контрактное программирование". Уж лучше программирование по контракту. Если отбросить вопросы верификации, то контракт - это соглашение между программистами по поводу интерфейсов. Как только такое соглашение достигнуто и интерфейсы специфицированы, каждый независимый модуль может писать отдельно взятый программист. И сколь бы не была сложна и объёмна задача, программу всегда можно разделить на независимые модули, которые в конце объединить и получить программный продукт. 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, 12:56 |
| Перечитал. Надо вычищать и расширать. А может первые 2 примера на plain C "вкорячить", а не на ++? Хотя... |
| Автор: mes 15.4.2010, 13:50 |
| kemiisto, ooo.. это что эпидемия ?! ну а если серьезно, то похвально.. к коду пока не приглядывался, но откуда взялся static ?! ну и критика статьи : имхо не стоит уделять время, и место для публикации реализации, достаточно освещать только интерфейс, ну и лишь некоторые моменты реализации, заслуживающие отдельного внимания.. кстати в этим будет еще раз показан смысл АТД - есть интерфейс и понятно как с ним работать, а какая там реализация клиенту даже задумаваться не надо. |
| Автор: kemiisto 15.4.2010, 14:26 |
От балды. Я почитал - нельзя никак. Ну кроме как явно для каждой переменной. static - от балды, компилятор "подсказал". |
| Автор: mes 15.4.2010, 14:34 | ||
при "статическом top`e" использовать два стека не получится .. сами себе палку в колеса поставили |
| Автор: kemiisto 15.4.2010, 14:35 | ||
Да я понял уже. И ведь сказал же - мне не интересно слушать, что это ошибка. Я хочу видеть решение. |
| Автор: mes 15.4.2010, 14:38 | ||
на то он и Си и в этом его сила Добавлено через 56 секунд
ну так мне казалось решение очевидно... выкинуть static |
| Автор: kemiisto 15.4.2010, 14:42 |
Да, логично. Бывает. |
| Автор: mes 15.4.2010, 14:49 | ||
| также если следовать правилам хорошего тона, то у стека должен быть метод top() для доступа к верхнему значению.. имхо, не очень удачное название.. лучше приучать читателя сразу к общепринятым (по крайней мере для С++) наименованиям.. Добавлено @ 14:55
А вот тут я не понял к какому выводу подталкивают читателя... Те "преимущества" представленные перед цитатой, это лишь следствия выбранного способа реализации классов. Ну а основное, ради чего ввели классы, должно будет представлено во второй части статьи : |
| Автор: kemiisto 15.4.2010, 15:05 | ||||||
Разве? По-моему нужен только push()/pop(). Остальное - опционально. Я уж и так тут добавил. Ладно, подумаю.
Ну можно... size()? Как это не поняли, если дальше и написали:
|
| Автор: mes 15.4.2010, 15:34 |
Дело в том, что обсуждаемая цитата хотя в общем контексте и понятна и "безопасна", но, мне показалось, несет скрытый подтекст.. хотя может просто сказалось выработанная привычка ожидать от Вас подвоха в сторону С++ |
| Автор: kemiisto 15.4.2010, 15:48 | ||
|
| Автор: bsa 15.4.2010, 17:04 |
| ну развели тут, понимаешь ли... Ладно. продолжайте, если в итоге что-то хорошее выйдет, можно будет в ФАК засунуть. |
| Автор: mes 15.4.2010, 19:28 | ||
это не отражено в коде.. хотя и не знаю надо ли.. в общем предлагаю для лучшего абстрагитования затайпдефить int к stack_value_t или просто к Т. |
| Автор: kemiisto 15.4.2010, 19:31 |
Кому дадено, тот увидит. В парочке мест заменить int на another_type - не проблема. |
| Автор: mes 15.4.2010, 19:41 |
шаблоны лучше приберечь напоследок, но если глава статьи посвящена абстракции, то желательно читателю изначально дать почувствовать ее красоту и силу |
| Автор: qweqwe 16.4.2010, 13:21 |
| Капитан Очевидность покусал kemiisto |