Чи C ++ не підходить для OOP? [зачинено]


12

Я читав десь в одній з відповідей на питання тут (не пам'ятаю, який), що C ++ не підходить для об'єктно-орієнтованого програмування. Деякі згадували, що ви можете скористатися його функцією чи чимось подібним, але не в чистому сенсі OOP (я насправді не дуже розумів, що означає людина).

Чи є в цьому якась правда; якщо так, то чому?



5
OOP не є чітко визначеним терміном, тому обговорювати, чи є C ++ є чи не підходить, досить безглуздо.
zvrba

Відповіді:


31

Як описано в Отже, що * мав на увазі Алан Кей під терміном "об'єктно-орієнтований"? , Алан Кей подумав, що передача повідомлень є важливим бітом OOP, але це те, чого не вистачає "C з класами" (які згодом стали C ++). C ++ просто взаємодіє з деякою поведінкою, тоді як об'єкти в Smalltalk або Objective-C є "розумними", оскільки вони можуть вирішити, що робити з повідомленнями, які вони надсилають. Якщо об’єкт-ескіз Smalltalk отримує повідомлення, для якого воно не має реалізації, він може ліниво додати його, переслати повідомлення іншому об'єкту або зробити будь-яку довільну річ.

Що C ++ пропонує у вигляді об'єктної орієнтації - це virtualметоди та поліморфізм із залученням цих методів. Коли компілятор бачить тип даних (або class), у яких є віртуальні методи, він конструює vtable із слотом для кожного віртуального методу. Підкласи, що реалізують віртуальні методи, ставлять їх реалізацію у правильні слоти, тому клієнтський код просто повинен знати, де у віртуальній таблиці шукати код для запуску, а не вирішувати його аж до певної функції. Що це означає, що C ++ ефективно робить мати форму множини відправки, хоча все це реалізовано в компіляторі і не так здатні , як Smalltalk-еск системи.

Якщо ви вважаєте, що передача повідомлень є основним для OOP, то, хоча ви можете це зробити за допомогою C ++, це далеко не просто. OTOH, якщо ви вважаєте, що OOP означає асоціювання даних із функціями, які діють на цих даних, C ++ - це добре.


8
+1 - але я завжди вважав, що виклик функції є розумним способом передавати повідомлення в будь-якому випадку. Правда, це фундамент низького рівня, а не виправлення на високому рівні для всього - але шаблон активних об'єктів показує, що можна будувати з цього фундаменту.
Steve314

6
тож це стосується не лише C ++, але й Java, C #, Object Pascal тощо. І в кінцевому підсумку це означає, що система обміну повідомленнями Windows API - це те, що Алан мав на увазі як найважливіше в OOP, особливо як це обробляє Delphi
Тринідад

@trinidad правильна, за винятком того, що C # насправді підтримує динамічну роздільну здатність. Я думаю, що справедливо сказати, що наша ідея OOP з часом змінилася, щоб подолати відсутність передачі повідомлень. Допомогли виробники без сумніву, що їхні технології, безумовно, є OOP на

@ steve314 так. Дійсно так працює ObjC, відправка повідомлення переводиться на виклик функції, який шукає і викликає функцію методу. Як я розумію, передача повідомлень є важливою для подвійної відправки.

1
@Paul: Маючи обмежений досвід роботи з API Win32, я не розумію. Будь-який API, де об'єкти мають різний розмір, і де потрібно спершу викликати розпорядок, щоб визначити, наскільки об'єкт буде великим, виділити пам'ять та викликати його ще раз, не піддається моєму тесту на красу.
Девід Торнлі

27

Цей вид дискусії мене турбує, тому що це звучить як екзегеза, люди, які обговорюють значення Священного Писання чи американської Конституції, і те, що мали на увазі оригінальні автори, ніби те, що, на нашу думку, не має значення.

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

Він не Месія, і ООП не є єдиною парадигмою програмування.

Це гарна ідея, серед багатьох. Чи є в C ++ хороші ідеї в ньому, виходячи з розуму OOP? Звичайно, так і є.


8

C ++ підтримує OOP, якщо ви визначаєте, що OOP означає інкапсуляцію, успадкування та поліморфізм.

Однак C ++ насправді не відрізняється від OOP. Однією з причин є те, що поліморфізм часто залежить від об'єктів, виділених з купи, з якими (незважаючи на використання розумних покажчиків), більш природно працювати з мовою, зібраною зі сміттям.

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


4

C ++ запозичила функції OOP від ​​Simula. Один або кілька розробників Simula IIRC прокоментували, що C ++ - це не те, що вони мали на увазі.

C ++ має хороші інструменти для абстрагування, але це скоріше мова змішаної парадигми, ніж мова, орієнтована на об'єкти. Об'єктно-орієнтовані функції є, але у вас є вибір, який не є "суворим OOP".

Одне з пустотливих «відмов» від C ++ - це використання методів раннього, а не пізнього прив'язки. Це не тільки можливо - це за замовчуванням. У Java "final" пов'язаний, але чистішим у чомусь (він вказує намір таким чином, який не стосується лише уникнення тривіальної продуктивності), і це не за замовчуванням.

У чомусь C ++ виявляє ознаки раннього експерименту, який все ще є тут. Тим не менш, це все-таки хороший інструмент, маючи багато переваг, яких ви не отримуєте в інших мовах OOP.


2
C ++ дозволяє не-OOP, а C ++ дозволяє OOP, для деяких мов бути OO, він повинен дозволяти OOP, тому C ++ є мовою OO.
Тринідад

1
Я вважаю, що Алан Кей, слава Smalltalk, сказав, що C ++ - це не те, що він мав на увазі, коли ввів термін "об'єктно-орієнтований". Оскільки C ++ стартував як "C з класами", перенесення класів Simula на C, і ніколи не робив чистого перерви, не дивно, що це виглядає як ранній експеримент.
Девід Торнлі

1
@Trinidad: БУДЬ-яка мова дозволяє OOP. Я бачив досить багато приємного коду OO у звичайному старому C. Так, це болю, визначаючи всі таблиці віртуальних методів вручну, але мова явно це дозволяє .
Ян Худек

4

Примушування всього бути частиною класу не обов'язково дає великий код OO.

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

У Java є оператор перемикання. Я бачив switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }і т. Д. І в C ++, і в коді Java.

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

Основна "погана" семантика в C ++ - це можливість копіювати побудову класів, за допомогою яких об'єкт перетворюється на інший. Ви можете відключити це, але потім ви не можете повернути його з функції. На щастя, це вирішено в C ++ 0x.


3

OOP не лише в тому, щоб переконатися, що все є або є в класі. Цілком можливо писати код, що не є OO, "чисто OO" мовою. Наприклад, на "main" часто вказують як на глобальну функцію, але винаходити клас виключно для того, щоб містити статичний основний метод - це так само, як не-OO.

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


2

C ++ можна використовувати для OOP, але він не такий "чистий", як щось на зразок Smalltalk. C ++ також дозволяє вам робити не OOP, про що люди можуть говорити.


2

Хоча я не згоден з настроями, правда, система типів C ++ не є чистою OOP - не "все є об'єктом". Числа (зокрема) не можуть бути розширені настільки швидко, наскільки це можливо, скажімо, у Smalltalk. Ви не можете переосмислити, наприклад, значення "2 + 2" (хоча ви можете переосмислити значення "два + два").

Але, напевно, мається на увазі те, що багато людей пишуть не об’єктно-орієнтований код на C ++, але вважають, що оскільки вони використовують "OOP" мову, вони орієнтовані на об'єкти. Що це не так. Але, на мою думку, ви можете написати жахливий імперативний код у Smalltalk і не бути кращим за гідний дизайн OOP в C ++.


1

Цілком справедливим запереченням Алана Кей щодо C ++ було те, що це мова макросів на вершині C.

Поняття "передача повідомлення" - це просто думка про те, що екземпляри занять зберігаються в пам'яті і вони розкривають методи, які можна викликати. Передача повідомлень * моделюється в C ++ за допомогою vtables, що містять покажчики на функції.

Сказати, що передача повідомлень не існує в C ++, є неточним, що точніше сказати - це те, що передача повідомлень є невід'ємною частиною інших мов.

Це дуже семантичний мовний дизайн-аргумент, який я підозрюю, що трохи перевищує рівень досвіду запитувача.

За словами, є тисяча причин ненавидіти C ++, і дуже мало причин любити це.

Замість того, щоб шукати ідеальний молоток та ідеальний цвях, знайдіть ідеальний будинок, який потрібно побудувати, а потім знайдіть потрібні інструменти ... що потребує досвіду.

Також важливо пам’ятати, що в системах програмування те, чого боїться Алан Кей, не є «чистим OOP», - це фактично сила C ++. Кожному своє...


1
Об'єктив C також починається як макромовна мова на вершині C, але є об'єктно орієнтованою мовою.
Ян Худек

1

На мою думку, це не стільки визначене питання, скільки питання зручності використання.

Об'єкти - це абстракція, покликана полегшити читання, запис та міркування про складні програми. Для практичного програміста, чи відповідає мова всім критеріям конкретного формального визначення "об'єктно-орієнтованого" (здається, що існує декілька конкуруючих!), Насправді не так важливо, наскільки підходящі для роздумів інструменти, які він пропонує ваша програма з точки зору зазначених об'єктів - тобто фактично отримує передбачувані переваги продуктивності OOP.

У C ++ об'єкти - це дуже жахливі абстракції, які часто змушують програмістів стикатися з неприємними питаннями, пов’язаними з тим, як ці об’єкти структуровані в пам'яті - питання, які більше нагадують кодування в прямому C, ніж інші мови OOP. Наприклад, відповіді, що часто запитують на C ++, пропонують таку критику (серед інших):

Для практикуючого дуже вигідно ознайомитись із системами OO, відмінними від C ++, та з визначеннями OO, відмінними від трійці "інкапсуляція, успадкування, поліморфізм", інтерпретовані спеціальними способами, що дозволяють C ++ вважатися "OO". Наприклад, твердження про те, що навколишнє середовище, якому не вистачає перевірки кордонів або збирання сміття, не є середовищем ОО, звучить неприємно для людей, звикших до C ++. Але з багатьох точок зору це має багато сенсу. Якщо хтось може перезаписати об’єкт, де "інкапсуляція"? Якщо розміщення об'єкта може призвести до звисання посилань або витоку пам'яті, як система "об'єктно-орієнтована" ? А як із вмінням розповісти, який вид об’єкта розташований у заданому місці та часі? Ви кажете, що програмне забезпечення працює з об’єктами - де вони? І якщо цього не вдається дізнатися, як слід налагоджувати програмне забезпечення?

C ++ об'єктно-орієнтована, але неприємно і неповно: її користувачі повинні докласти чимало зусиль, щоб переконатися, що їхні дані справді ведуть себе як "справжні" об'єкти, а не бітові помилки. З цього приводу багато кодів було написано на C ++ впродовж його життєвого циклу, більшість із них використовує класи та динамічну диспетчерику, тому це, очевидно, те, що ви можете використовувати для практичного OOP.


-1 для посилання на FQA у тому, що має бути серйозною відповіддю. FQA - це гніздо спотворень, напівправди та непорозумінь.
Девід Торнлі

@DavidThornley Це конкретна цитата - спотворення, напівправду чи непорозуміння?
Алекс П

Десь там. Ствердження про те, що мова OO повинна мати перевірку кордонів (іноді вбудованих у стандартні контейнери C ++ так чи інакше) та збирання сміття (розумні покажчики є примітивним збиранням сміття) є вимушеним та необережним. Речення про мову, яка дозволяє звисаючим посиланням не орієнтуватися на об'єкти, явно є доказом кричущого твердження. Мене спантеличує "вміння розповісти, який предмет"; тип вказівника видає його для об'єктів без віртуальної поведінки, а RTTI обробляє його для об'єктів з віртуальною поведінкою.
Девід Торнлі

@DavidThornley Ствердження FQA полягає в тому, що в корисній мові ОО повинні бути ці речі - що відповідає питанню, яке задається (чи C ++ "підходить"?). Я думаю, що претензія щодо визначень голих кісток насправді не стосується цього ... "Здатність розповісти": звичайна помилка поведінки під час доступу до об'єкта, якого насправді немає, шляхом слідування вказівника на деякі неініціалізовані або попередньо перезаписані дані; і ваша програма з радістю прийме цей сміття та інтерпретуватиме його як дані, а потім слідкує за покажчиками сміття до інших даних про сміття, поки він не потрапить у позасерединну адресу або не з’явиться якась помилка.
Алекс П

Однак цитата, принаймні, настійно підказує твердження, що мова без перевірки меж або збирання сміття не є ООС, і ігнорує той факт, що у вас є ці речі в C ++, якщо вам це подобається. Питання про те, чи перешкоджає мова певних класів помилок чи ні (з будь-якої причини), є ортогональним щодо того, чи є це OO.
Девід Торнлі

-1

Є причина, чому Грем Лі мав найбільше прибутків тут. Для повторного повторення виявляється, що клас C ++ насправді не є об'єктом у тому сенсі, що він не виконує передачу повідомлення. Я думаю, що це те, що значно подорожує людей, коли вони навчаються C ++ або oop. Людям кажуть, що об'єктно-орієнтоване - це «це», а потім кажуть, що C ++ робить це інакше. Що ж, C ++ ніколи не робив OOP по-іншому. Якщо ви думаєте, що таким чином ви ніколи не оціните класи C ++ за те, для чого вони призначені, і це те, що вони є лише вдосконаленням процедурної парадигми, включаючи абстракцію та динамічну поведінку. Таким чином, класи C ++ є фундаментально процесуальними, вони просто вдосконалюються внаслідок процедурної парадигми, вірніше, вони є більш досконалою версією С-структури.


Чи є у вас фактичні підтверджуючі причини ваших аргументів? Ви, здається, висловлюєте твердження і стверджуєте, що ті, хто не погоджуються, повинні помилитися, або змінили б свою думку, якби по-іншому дивились на це, або, можливо, якщо вони поділили ваше точне визначення ОО.
Девід Торнлі

Справедливо. Ви можете прочитати цю статтю . Я думаю, що я говорив, що c ++ не є "об'єктно-орієнтованим програмуванням" в суворому сенсі Алана Кей. Однак якщо ви визначаєте OOP як структуру даних з поведінкою, ви можете розглядати c ++ як OOP. На мій погляд, хоча точніше розглядати клас c ++ як абстракцію процедурного програмування вищого рівня. Клас c ++ набагато ефективніший, ніж об'єкт у стилі Kay, але гірший для одночасності. Особисто я вважаю, що клас c ++ - це чудовий дизайн.
дратівливий_скворіт

1
Дякую за посилання, але це лише пояснює, що мав на увазі Алан Кей. Більше того, я не погоджуюся з тим, що Smalltalk взагалі вважається першою мовою ОО, і Вікіпедія погоджується зі мною, що це була Simula, одна з двох мов Stroustrup, об'єднана у формі C з класами. Мене цікавить ваше твердження, що клас C ++ - це швидше абстракція процедурного програмування вищого рівня, ніж шаблон об'єкта, але я все ще не розумію, чому ви так думаєте.
Девід Торнлі

Об'єктна орієнтація - це, мабуть, суб'єктивний термін, якщо ми можемо з цим погодитися. Але я бачу об'єкт Kay як більш природний спосіб роз'єднати код і ввести одночасну модульність у тому сенсі, що кожен об'єкт виконує роль, як міні-комп'ютери, взаємодіючі при передачі повідомлень. За цією моделлю не повинно бути коду "між" b / c, вся логіка програми може бути виражена у вигляді комірок та повідомлень. Для порівняння, використання 'класів' зазвичай вимагає певного процесуального коду клею між ними (бракує справжньої модульності), але перевага полягає в тому, що класи набагато ефективніші.
дратівливий_шкріб

-1

Стів Йегге сказав найкраще :

C ++ - найглуміша мова на землі, в тому, що вона є найменш розумною. Це не знає про себе.

Об'єктна система в C ++ настільки провідна і фіксована під час компіляції, що вона дуже далека від початкового поняття OOP, що включає передачу повідомлень, самоаналіз, рефлексію, динамічне відправлення та пізнє прив'язування, між іншим. Єдине, що спільного для C ++ та Smalltalk - це трохи словникового запасу.


Яким чином C ++ є найменш чуттєвою мовою? Що означає мова, яка має розум? Якщо ви маєте на увазі, що йому не вистачає можливостей відображення, це досить часто, і, звичайно, не вибирає C ++ з натовпу.
Девід Торнлі

2
Як же ти можеш сказати, що він сказав це "найкраще"? Я поняття не маю, що означає ця випадкова цитата.
user16764

+1, кажучи, що подібні речі отримають багато пошкоджень від басейнів C ++, але це потрібно сказати - ви не можете насправді OOP без роздумів, тому що у вас немає дженериків, щоб піклуватися про горизонтальні речі ( аспекти) - життєвий цикл (активація, утилізація), загальне поводження з помилками, загальне наближення, загальна серіалізація, паралелізм загальних завдань - вони в кінцевому підсумку забруднюють ваш код і порушують SoC.
vski

Дякую. Я не можу повірити, що мені дісталося -3, сказавши, що мова без роздумів не є гарним прикладом ООП.
Джон Кромарті

1
@JohnCromartie, Не могли б ви детальніше зупинитися на цьому питанні у своїй відповіді?
Джеремі Хайлер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.