Чи 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.