С ++ не подходит для ООП? [закрыто]

12

Я прочитал где-то в одном из ответов на вопрос здесь (не помню, какой), что C ++ не подходит для объектно-ориентированного программирования. Были некоторые упоминания о том, что вы можете использовать его функцию или что-то в этом роде, но не в чисто ООП-смысле (на самом деле я не совсем понял, что имел в виду этот человек).

Есть ли в этом доля правды? если так, то почему?

gablin
источник
5
ООП не является четко определенным термином, поэтому обсуждать, подходит ли C ++ или нет, довольно бессмысленно.
zvrba

Ответы:

31

Как описано в разделе Так, что * на самом деле * Алан Кей имел в виду под термином «объектно-ориентированный»? Алан Кей считал, что передача сообщений является важным битом ООП, но это тот бит, которого не хватает в «C с классами» (который позже стал C ++). C ++ просто структурирован с небольшим поведением, тогда как объекты в Smalltalk или Objective-C «интеллектуальны» в том смысле, что они могут решать, что они делают с отправляемыми сообщениями. Если объект Smalltalk-esque получает сообщение, для которого у него нет реализации, он может лениво добавить его, переслать сообщение другому объекту или выполнить любую произвольную вещь.

Что C ++ предлагает в отношении объектной ориентации, так это virtualметоды и полиморфизм, включающие способ вызова этих методов. Когда компилятор видит тип данных (или class) с виртуальными методами, он создает виртуальную таблицу со слотом для каждого виртуального метода. Подклассы, которые реализуют виртуальные методы, поместят свои реализации в правильные слоты, поэтому клиентскому коду просто нужно знать, где в виртуальной таблице искать код для выполнения, а не разрешать его полностью до конкретной функции. Это означает, что C ++ действительно имеет форму множественной диспетчеризации, хотя все это реализовано в компиляторе и не так эффективно, как система Smalltalk-esque.

Если вы принимаете передачу сообщений за основу для ООП, то, хотя вы можете сделать это с C ++, это далеко не просто. OTOH, если вы используете OOP для обозначения связи данных с функциями, которые работают с этими данными, C ++ - это хорошо.

Сообщество
источник
8
+1 - но я всегда думал, что вызов функции - это разумный способ передать сообщение. Правда, это фундамент низкого уровня, а не исправление высокого уровня для всего - но шаблон активных объектов показывает, что его можно построить из этого фундамента.
Steve314
6
так что это относится не только к C ++, но и к Java, C #, Object Pascal и т. д. И в конечном итоге система сообщений Windows API - это то, что Алан имел в виду как наиболее важная вещь в ООП, особенно то, как она обрабатывается Delphi
Тринидад
@trinidad правильно, за исключением того, что C # на самом деле поддерживает динамическое разрешение. Я ожидаю, что будет справедливо сказать, что наша идея ООП со временем изменилась, чтобы обойти отсутствие передачи сообщений. Без сомнения, поставщики утверждают, что их технология определенно является ООП перед лицом доказательств ...
@ steve314 да, это так. Действительно, именно так работает ObjC, отправка сообщения преобразуется в вызов функции, которая ищет и вызывает функцию метода. Как я понимаю, передача сообщений важна, так как это двойная отправка.
1
@ Пол: Имея некоторый ограниченный опыт работы с Win32 API, я не понимаю. Любой API, где объекты имеют переменный размер и где необходимо сначала вызвать подпрограмму, чтобы определить, насколько большим будет объект, выделить память и снова вызвать его, не проходит мой тест на красоту.
Дэвид Торнли
27

Такое обсуждение беспокоит меня, потому что это звучит как толкование, люди обсуждают значение Священного Писания или американской Конституции и то, что имели в виду первоначальные авторы, как будто то, что мы думаем, не имеет значения.

Послушайте, Алан Кей был / был умным парнем, и у него была хорошая идея, которая натерлась на кучу других хороших идей и нашла свою реализацию на Smalltalk и других языках.

Он не Мессия, а ООП - это не Единственная Истинная Парадигма Программирования.

Это хорошая идея, среди многих. Есть ли в C ++ хорошие идеи, исходящие из мышления ООП? Конечно, это так.

Майк Данлавей
источник
8

C ++ поддерживает ООП, если вы определяете ООП для обозначения инкапсуляции, наследования и полиморфизма.

Тем не менее, C ++ не особо выделяется в ООП. Одна из причин заключается в том, что полиморфизм часто зависит от объектов, размещенных в куче, с которыми (несмотря на использование интеллектуальных указателей) более естественно работать в языке с мусором.

Однако C ++ превосходит универсальное программирование. C ++ позволяет легко создавать высокоэффективный общий код с помощью методов функционального программирования на основе шаблонов.

Чарльз Сальвия
источник
4

C ++ позаимствовал функции ООП от Simula. Один или несколько разработчиков Simula IIRC отметили, что C ++ - это не то, что они имели в виду.

C ++ имеет хорошие инструменты для абстракции, но это скорее язык со смешанной парадигмой, чем объектно-ориентированный язык. Объектно-ориентированные функции есть, но у вас есть выбор, который не является «строгим ООП».

Одним из непослушных «отказов», которые вы получаете в C ++, является использование раннего, а не позднего связывания для методов. Мало того, что это возможно - это по умолчанию. В Java «финал» связан, но в некотором смысле чище (он задает намерение таким образом, который не просто предотвращает тривиальные потери производительности), и он не используется по умолчанию.

В некотором смысле, C ++ показывает признаки того, что это ранний эксперимент, который все еще здесь. Тем не менее, это все еще хороший инструмент с множеством преимуществ, которых вы не получите на других языках ООП.

Steve314
источник
2
C ++ допускает не-ООП, а C ++ допускает ООП, для некоторых языков, чтобы быть ОО, он должен разрешать ООП, поэтому C ++ является языком ОО.
Тринидад
1
Я полагаю, что Алан Кей, известный в Smalltalk, сказал, что C ++ не был тем, что он имел в виду, когда придумал термин «объектно-ориентированный». Так как C ++ начинался как «C с классами», прививая классы Simula к C, и никогда не совершал чистый разрыв, неудивительно, что это похоже на ранний эксперимент.
Дэвид Торнли
1
@ Тринидад: ЛЮБОЙ язык позволяет ООП. Я видел довольно много приятного ОО-кода на старом старом языке C. Да, очень сложно определять все таблицы виртуальных методов вручную, но язык это явно позволяет .
Ян Худек
4

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

Попросите плохого процедурного программиста программировать на Java, и он, возможно, возьмет где-нибудь класс, даст ему статический метод main и вставит в него 1000 строк кода. Я знаю, что видел это.

У Java есть оператор switch. Я видел switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }и т.д. в C ++ и Java-коде.

C ++ поддерживает многие концепции ОО, но его стандарт не определяется им, однако, я думаю, многое зависит от вашей цели.

Основная «плохая» семантика в C ++ позволяет копировать классы, в результате чего объект превращается в другой. Вы можете отключить это, но затем вы не можете вернуть один из функции. К счастью, это решено в C ++ 0x.

Дойная корова
источник
3

ООП - это не просто уверенность в том, что все в классе. Вполне возможно написать не OO-код на «чисто OO-языке». Например, «main» часто указывается как глобальная функция, но изобретение класса, содержащего только статический метод main, совсем не как OO.

C ++ лучше всего работает с различными вещами; это не должно удивлять, так как большинство хороших вещей работают лучше всего. Часто ООП является одним из тех очень полезных инструментов.

Фред Нурк
источник
2

C ++ можно использовать для ООП, но он не такой «чистый», как что-то вроде Smalltalk. C ++ также позволяет вам делать не-ООП, о чем люди могут говорить.

Craig
источник
2

Хотя я не согласен с мнением, это правда, что система типов C ++ не является чистой ООП, а не «все является объектом». Числа (в частности) не могут быть расширены так легко, как, например, в Smalltalk. Например, вы не можете переопределить значение «2 + 2» (хотя вы можете переопределить значение «два + два»).

Но большинство людей, вероятно, имеют в виду, что многие люди пишут не объектно-ориентированный код на C ++, но считают, что, поскольку они используют язык «ООП», они объектно-ориентированы. Это не правда. Но, на мой взгляд, вы можете написать отвратительный императивный код на Smalltalk и не превзойти приличный дизайн ООП в C ++.

Ларри Обриен
источник
1

Совершенно обоснованное возражение Алана Кея против C ++ заключалось в том, что это был макроязык над C.

Понятие «передача сообщений» - это просто идея о том, что экземпляры классов хранятся в памяти и что они предоставляют методы, которые можно вызывать. Передача сообщений * моделируется "в C ++ с использованием таблиц vtables, содержащих указатели на функции.

Сказать, что передача сообщений не существует в C ++, неточно, но точнее сказать, что передача сообщений является неотъемлемой частью других языков, таких как smalltalk и Java, потому что язык не обрабатывает стороннюю конструкцию и не прививает ее непосредственно в C.

Это очень семантический аргумент в пользу языкового дизайна, который, как я подозреваю, немного превышает уровень опыта спрашивающего.

Тем не менее, есть тысячи причин ненавидеть C ++ и очень мало причин любить его.

Вместо того, чтобы искать идеальный молоток и идеальный гвоздь, найдите идеальный дом для строительства, а затем найдите правильные инструменты ... это требует опыта.

Также важно помнить, что в системном программировании то, чего боится Алан Кей, не является «чистым ООП», на самом деле является сильной стороной C ++. Каждому свое...

bobx
источник
1
Цель C также начиналась как макроязык поверх C, но это объектно-ориентированный язык.
Ян Худек
1

На мой взгляд, это не столько проблема определения, сколько проблема юзабилити.

Объекты - это абстракция, предназначенная для облегчения чтения, написания и анализа сложных программ. Для практического программиста то, соответствует ли язык всем критериям определенного формального определения «объектно-ориентированного» (кажется, что есть несколько конкурирующих!), Не так важно, как подходящие инструменты, которые он предлагает, для размышлений ваша программа с точки зрения указанных объектов - т.е. фактически пожинает предполагаемые преимущества производительности ООП.

В C ++ объекты представляют собой чрезвычайно утечку абстракций, часто заставляющую программистов сталкиваться с неприятными проблемами, связанными с тем, как эти объекты структурированы в памяти, - проблемами, которые больше напоминают кодирование на прямом C, чем в других языках ООП. Например, C ++ Часто задаваемые вопросы предлагает эту критику (среди прочих):

Для практикующего специалиста очень полезно ознакомиться с ОО-системами, отличными от С ++, и с определениями ОО, отличными от троицы «инкапсуляция, наследование, полиморфизм», которые интерпретируются особым образом, позволяя рассматривать С ++ как «ОО». Например, утверждение о том, что среда, в которой отсутствует проверка границ или сборка мусора, не является ОО-средой, звучит возмутительно для людей, привыкших к C ++. Но со многих точек зрения это имеет большой смысл. Если кто-то может перезаписать объект, где находится «инкапсуляция»? Если удаление объекта может привести к зависанию ссылок или утечке памяти, как система «объектно-ориентирована» ? А как насчет способности сказать, какой объект находится в данном месте и времени? Вы говорите, что программное обеспечение работает с объектами - где они? И если не удается выяснить, как можно отлаживать программное обеспечение?

C ++ является объектно-ориентированным, но неприятным и неполным: его пользователи должны приложить немало усилий, чтобы убедиться, что их данные на самом деле ведут себя как «реальные» объекты, а не как ошибочные биты. Тем не менее, много кода было написано на C ++ за время его жизни, большая часть которого использует классы и динамическую диспетчеризацию, так что это само собой разумеется, что вы можете использовать для практического ООП.

Алекс П
источник
-1 для ссылки на FQA в том, что должно быть серьезным ответом. FQA - это гнездо искажений, полуправды и недоразумений.
Дэвид Торнли
@DavidThornley Является ли конкретная цитата искажением, полуправдой или недоразумением?
Алекс П
Где-то там. Утверждение о том, что язык ОО должен иметь проверку границ (иногда в любом случае встроенную в стандартные контейнеры C ++) и сборку мусора (умные указатели являются примитивной сборкой мусора), является вынужденным и неискренним. Предложение о языке, который позволяет висящим ссылкам не быть объектно-ориентированными, явно доказано Blatant Assertion. Я озадачен «способностью сказать, что это за объект»; тип указателя выдает его для объектов без виртуального поведения, а RTTI обрабатывает его для объектов с виртуальным поведением.
Дэвид Торнли
@DavidThornley Заявление FQA состоит в том, что полезный язык OO должен иметь эти вещи - что соответствует задаваемому вопросу («C ++« подходит »?). Я думаю, что утверждение об основных определениях на самом деле не относится к этому ... «Способность сказать»: распространенная ошибка при доступе к объекту, которого на самом деле нет, следуя указателю на некоторые неинициализированные или ранее перезаписанные данные; и ваша программа с радостью возьмет этот мусор и интерпретирует его как данные, а затем будет следовать указателям мусора на другие данные мусора, пока не достигнет адреса за пределами допустимого диапазона или не произойдет какая-либо серьезная ошибка.
Алекс П
Тем не менее, цитата, по крайней мере, настоятельно предложила утверждение, что язык без проверки границ или сборки мусора не является ОО, и проигнорировала тот факт, что у вас есть эти вещи в C ++, если хотите. Вопрос о том, предотвращает ли язык определенные классы ошибок или нет (по какой-либо причине), является ортогональным по отношению к тому, является ли он ОО.
Дэвид Торнли
-1

Есть причина, по которой у Грэма Ли было больше всего голосов. Повторюсь, похоже, что класс C ++ на самом деле не является объектом в том смысле, что он не выполняет передачу сообщений. Я думаю, это то, что запутывает людей, когда они изучают C ++ или упс. Людям говорят, что объектно-ориентированным является «это», а затем говорят, что C ++ делает это по-другому. Ну, C ++ никогда не делал ООП иначе. Если вы думаете так, вы никогда не будете ценить классы C ++ за то, для чего они предназначены, и это то, что они являются просто улучшением процедурной парадигмы путем включения абстракции и динамического поведения. Таким образом, классы C ++ являются процедурно-процедурными, они просто улучшают процедурную парадигму или, скорее, являются более продвинутой версией структуры C.

annoying_squid
источник
У вас есть какие-либо действительные обоснования ваших аргументов? Похоже, вы делаете утверждения и утверждаете, что те, кто не согласен, должны ошибаться или передумать, если они по-другому смотрят на это, или, возможно, разделяют ваше точное определение ОО.
Дэвид Торнли
Справедливо. Вы можете прочитать эту статью . Я предполагаю, что я говорил, что c ++ не является «объектно-ориентированным программированием» в строгом смысле слова Алана Кея. Однако если вы определяете ООП как структуру данных с поведением, то вы можете рассматривать С ++ как ООП. Однако, на мой взгляд, точнее рассматривать класс c ++ как абстракцию процедурного программирования более высокого уровня. Класс c ++ намного эффективнее объекта стиля Kay, но хуже для параллелизма. Лично я думаю, что класс C ++ - отличный дизайн.
annoying_squid
1
Спасибо за ссылку, но она только объясняет, что имел в виду Алан Кей. Более того, я не согласен с тем, что Smalltalk обычно считается первым ОО-языком, и Википедия соглашается со мной в том, что это был Simula, один из двух языков, которые Stroustrup объединил в C с классами. Меня интересует ваше утверждение, что класс C ++ - это скорее абстракция процедурного программирования более высокого уровня, чем шаблон объекта, но я до сих пор не понимаю, почему вы так думаете.
Дэвид Торнли
Объектная ориентация, вероятно, является субъективным термином, если мы можем согласиться с этим. Но я вижу объект Kay как более естественный способ отделить код и ввести параллельную модульность в том смысле, что каждый объект выполняет роль мини-компьютера, взаимодействующего посредством передачи сообщений. В рамках этой модели не должно быть практически никакого кода «между», поскольку вся логика программы может быть выражена в виде ячеек и сообщений. Для сравнения, использование «классов» обычно требует некоторого процедурного связующего кода (отсутствует истинная модульность), но преимущество в том, что классы гораздо более эффективны.
annoying_squid
-1

Стив Йегге сказал это лучше всего :

C ++ - самый тупой язык в мире, в самом истинном смысле слова как наименее чувствительный. Он не знает о себе.

Объектная система в C ++ настолько жестко запрограммирована и исправлена ​​во время компиляции, что она очень далека от первоначального понятия ООП, которое включает, среди прочего, передачу сообщений, самоанализ, отражение, динамическую диспетчеризацию и позднее связывание. Единственное, что общего у C ++ и Smalltalk - это немного словарного запаса.

Джон Кромарти
источник
Как С ++ является наименее разумным языком? Что значит для языка быть разумным? Если вы имеете в виду, что в нем отсутствуют способности к отражению, это довольно распространенное явление, и, конечно, он не выбирает C ++ из толпы.
Дэвид Торнли
2
Как же ты мог сказать, что он сказал это «лучше»? Я понятия не имею, что означает эта случайная цитата.
user16764
+1 сказать, что такого рода вещи получат много удовольствия от взломщиков C ++, но нужно сказать - вы не можете по-настоящему ООП без отражения, потому что у вас нет универсальных средств, чтобы заботиться о горизонтальных вещах ( аспекты) - жизненный цикл (активация, удаление), универсальная обработка ошибок, универсальное проксирование, универсальная сериализация, универсальный параллелизм задач - все это в конечном итоге загрязняет ваш код и нарушает SoC.
вс
Благодарю. Я не могу поверить, что получил -3 за то, что сказал, что язык без размышлений не является хорошим примером ООП.
Джон Кромарти
1
@JohnCromartie, не могли бы вы уточнить этот момент в своем ответе?
Джереми Хейлер