Czy C ++ nie jest odpowiedni dla OOP? [Zamknięte]

12

Przeczytałem gdzieś w jednej z odpowiedzi na pytanie tutaj (nie pamiętam, które), że C ++ nie nadaje się do programowania obiektowego. Było kilka wzmianek, że możesz skorzystać z jego funkcji lub czegoś takiego, ale nie w czysto OOP (tak naprawdę nie rozumiałem, co ta osoba ma na myśli).

Czy jest w tym jakaś prawda; jeśli tak to dlaczego?

gablin
źródło
5
OOP nie jest dobrze zdefiniowanym terminem, więc omawianie, czy C ++ jest odpowiednie, czy nie, jest raczej bezcelowe.
zvrba

Odpowiedzi:

31

Jak opisano w Więc co * naprawdę * Alan Kay naprawdę miał na myśli termin „obiektowy”? Alan Kay pomyślał, że przekazywanie wiadomości było ważnym elementem OOP, ale jest to fragment, którego brakuje „C z klasami” (które później stały się C ++). C ++ to po prostu struktury z odrobiną zachowania, podczas gdy obiekty w Smalltalk lub Objective-C są „inteligentne”, ponieważ mogą decydować, co zrobią z wysłanymi wiadomościami. Jeśli obiekt Smalltalk otrzyma komunikat, dla którego nie ma implementacji, może leniwie dodać jeden, przekazać wiadomość do innego obiektu lub wykonać dowolną czynność.

C ++ oferuje w zakresie orientacji obiektowej virtualmetody i polimorfizm związane ze sposobem wywoływania tych metod. Gdy kompilator zobaczy typ danych (lub class), który ma metody wirtualne, konstruuje vtable z miejscem dla każdej metody wirtualnej. Podklasy, które implementują metody wirtualne, umieszczą swoje implementacje w odpowiednich gniazdach, więc kod klienta musi jedynie wiedzieć, gdzie w wirtualnej tabeli szukać kodu do uruchomienia, zamiast rozwiązywać go aż do konkretnej funkcji. Co to znaczy jest, że C ++ skutecznie robi mieć postać stwardnienia wysyłki, chociaż to wszystko jest realizowane w kompilator i nie jest jako zdolny jako system Smalltalk-esque.

Jeśli uważasz, że przekazywanie wiadomości ma podstawowe znaczenie dla OOP, to mimo że możesz to zrobić w C ++, nie jest to łatwe. OTOH, jeśli weźmiesz pod uwagę OOP jako powiązanie danych z funkcjami, które działają na tych danych, C ++ jest w porządku.

Społeczność
źródło
8
+1 - ale zawsze myślałem, że wywołanie funkcji jest rozsądnym sposobem na przekazanie wiadomości. To prawda, że ​​jest to podstawa niskiego poziomu, a nie poprawka wysokiego poziomu do wszystkiego - ale wzór aktywnych obiektów pokazuje, że można zbudować z tego fundamentu.
Steve314
6
więc dotyczy to nie tylko C ++, ale także Java, C #, Object Pascal itp. I w końcu system komunikatów Windows API jest tym, co Alan miał na myśli w OOP jako najważniejszą rzeczą, szczególnie sposób, w jaki obsługuje go Delphi
Trynidad
@ Trynidad poprawny, z tym że C # faktycznie obsługuje dynamiczną rozdzielczość. Oczekuję, że uczciwie jest powiedzieć, że nasz pomysł na OOP zmienił się z czasem, aby obejść brak przekazywania wiadomości. Pomagali bez wątpienia sprzedawcy twierdzący, że ich technologia jest zdecydowanie OOP w obliczu dowodów ...
@ steve314 tak to jest. Rzeczywiście tak działa ObjC, wysyłanie wiadomości jest tłumaczone na wywołanie funkcji, która wyszukuje i wywołuje funkcję metody. Jak rozumiem przekazywanie wiadomości, ważna jest podwójna wysyłka.
1
@Paul: Mam ograniczone doświadczenie z Win32 API, nie rozumiem. Każdy interfejs API, w którym obiekty mają zmienną wielkość i gdzie konieczne jest najpierw wywołać procedurę, aby określić, jak duży będzie ten obiekt, przydzielić pamięć i wywołać ją ponownie, nie przejdzie mojego testu na piękno.
David Thornley,
27

Tego rodzaju dyskusja niepokoi mnie, ponieważ brzmi to jak egzegeza, ludzie debatujący nad znaczeniem Pisma Świętego lub amerykańskiej konstytucji i co oryginalny autor (autorzy) mieli na myśli, tak jakby to , co myślimy, nie miało znaczenia.

Słuchaj, Alan Kay był / jest sprytnym facetem i miał dobry pomysł, który zatarł wiele innych dobrych pomysłów i został zrealizowany w Smalltalk i innych językach.

On nie jest Mesjaszem, a OOP nie jest jedynym prawdziwym paradygmatem programowania.

Jest to dobry pomysł spośród wielu. Czy C ++ ma dobre pomysły, wywodzące się z sposobu myślenia OOP? Oczywiście, że tak.

Mike Dunlavey
źródło
8

C ++ obsługuje OOP, jeśli zdefiniujesz OOP jako enkapsulację, dziedziczenie i polimorfizm.

Jednak C ++ tak naprawdę nie przoduje w OOP. Jednym z powodów jest to, że polimorfizm często zależy od obiektów alokowanych na stercie, które (bez względu na użycie inteligentnych wskaźników) są bardziej naturalne do pracy w języku zbierającym śmieci.

Jednak tam, gdzie C ++ przoduje, jest programowanie ogólne. C ++ pozwala łatwo tworzyć wysoce wydajny, ogólny kod za pomocą technik programowania funkcjonalnego opartych na szablonach.

Charles Salvia
źródło
4

C ++ pożyczył funkcje OOP od Simula. Jeden lub więcej deweloperów Simula IIRC skomentowało, że C ++ nie jest tym, co mieli na myśli.

C ++ ma dobre narzędzia do abstrakcji, ale jest to bardziej język mieszany paradygmat niż język obiektowy. Istnieją obiekty zorientowane obiektowo, ale masz opcje, które nie są „ścisłym OOP”.

Jednym z niegrzecznych „rezygnacji”, jakie otrzymujesz w C ++, jest stosowanie wcześniejszego niż późnego wiązania dla metod. Jest to nie tylko możliwe - jest to ustawienie domyślne. W Javie „końcowy” jest powiązany, ale pod pewnymi względami bardziej przejrzysty (określa intencję w sposób, który nie polega tylko na unikaniu trywialnego narzutu wydajności) i nie jest domyślny.

W pewnym sensie C ++ wykazuje oznaki bycia wczesnym eksperymentem, który wciąż tu jest. Mimo to jest to nadal dobre narzędzie z wieloma zaletami, których nie można uzyskać w innych językach OOP.

Steve314
źródło
2
C ++ pozwala na brak OOP, a C ++ pozwala na OOP, aby niektóre języki mogły być OO, musi zezwalać na OOP, dlatego C ++ jest językiem OO.
Trinidad
1
Uważam, że Alan Kay, znany ze Smalltalk, powiedział, że C ++ nie miał na myśli tego, kiedy wymyślił termin „obiektowy”. Ponieważ C ++ zaczęło się jako „C with Classes”, przeszczepienie klas Simula na C i nigdy nie zrobiło czystej przerwy, nic dziwnego, że wygląda jak wczesny eksperyment.
David Thornley,
1
@Trinidad: DOWOLNY język pozwala na OOP. Widziałem całkiem sporo ładnego kodu OO w zwykłym starym C. Tak, to ból definiuje ręcznie wszystkie tabele metod wirtualnych, ale język wyraźnie na to pozwala .
Jan Hudec
4

Wymuszanie, by wszystko było częścią klasy, niekoniecznie daje wspaniały kod OO.

Poproś biednego programistę proceduralnego, aby programował w Javie, a prawdopodobnie zabiorą gdzieś klasę, nadadzą jej statyczną metodę główną i wstawią do niej 1000 linii kodu. Wiem, że to widziałem.

Java ma instrukcję switch. Widziałem switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }itp. Zarówno w kodzie C ++, jak i Java.

C ++ obsługuje wiele koncepcji OO, ale jego standard nie jest przez nią zdefiniowany, ale myślę, że wiele zależy od tego, jaki jest twój cel.

Główny „słaby” semantyczny w C ++ pozwala na kopiowanie konstrukcji klas, dzięki czemu obiekt przekształca się w inny. Możesz to wyłączyć, ale nie możesz zwrócić żadnej z funkcji. Na szczęście jest to rozwiązane w C ++ 0x.

Dojną krową
źródło
3

OOP nie polega tylko na upewnieniu się, że wszystko jest w klasie. Zupełnie możliwe jest pisanie kodu innego niż OO w języku „czysto OO”. Na przykład „main” jest często wskazywane jako funkcja globalna, ale wynalezienie klasy zawierającej wyłącznie statyczną metodę główną jest tak samo niemożliwe.

C ++ działa najlepiej z wieloma różnymi rzeczami; nie powinno to być zaskakujące, ponieważ tak najlepiej działa większość dobrych rzeczy. Często OOP jest jednym z tych bardzo przydatnych narzędzi.

Fred Nurk
źródło
2

C ++ może być używany do OOP, ale nie jest tak „czysty” jak coś takiego jak Smalltalk. C ++ pozwala także na wykonywanie zadań bez OOP, o czym ludzie mogą mówić.

Craig
źródło
2

Chociaż nie zgadzam się z tym sentymentem, prawdą jest, że system typów C ++ nie jest czystym OOP - nie „wszystko jest przedmiotem”. Liczby (w szczególności) nie mogą być przedłużane tak łatwo, jak to możliwe, powiedzmy w Smalltalk. Na przykład nie można przedefiniować znaczenia „2 + 2” (chociaż można przedefiniować znaczenie „dwa + dwa”).

Ale większość ludzi prawdopodobnie ma na myśli to, że wiele osób pisze w języku C ++ kod nieobiektywny, ale wierzy, że ponieważ używają języka „OOP”, są zorientowani obiektowo. To nieprawda. Ale moim zdaniem możesz pisać ohydny imperatywny kod w Smalltalk i nie być lepszym od przyzwoitego projektu OOP w C ++.

Larry OBrien
źródło
1

Całkowicie uzasadnionym zastrzeżeniem Alana Kay'a do C ++ było to, że był to język makro na C.

Pojęcie „przekazywanie wiadomości” jest po prostu ideą, że instancje klas są przechowywane w pamięci i ujawniają metody, które można wywołać. Przekazywanie wiadomości jest * symulowane "w C ++ przy użyciu vtables przechowujących wskaźniki do funkcji.

Stwierdzenie, że przekazywanie wiadomości nie istnieje w C ++, jest niedokładne, dokładniejsze jest stwierdzenie, że przekazywanie wiadomości jest integralną częścią innych języków, takich jak smalltalk i Java, ponieważ język nie przetwarza obcego konstruktu i przenosi go bezpośrednio na język C.

Jest to wysoce semantyczny argument projektowania języka, który, jak podejrzewam, wykracza nieco poza poziom doświadczenia pytającego.

Biorąc to pod uwagę, istnieje tysiące powodów, aby nienawidzić C ++ i bardzo niewiele powodów, by go kochać.

Zamiast szukać idealnego młotka i idealnego gwoździa, znajdź idealny dom do zbudowania, a następnie znajdź odpowiednie narzędzia ... które wymagają doświadczenia.

Ważne jest również, aby pamiętać, że w programowaniu systemów, czego obawia się Alan Kay, nie jest „czysty OOP”, tak naprawdę jest siłą C ++. Do każdej jego własności...

Bobx
źródło
1
Cel C również zaczął się jako język makro na C, ale jest językiem obiektowym.
Jan Hudec
1

Moim zdaniem nie jest to kwestia definicyjna, ale kwestia użyteczności.

Obiekty są abstrakcją mającą na celu ułatwienie czytania, pisania i rozumowania złożonych programów. Dla praktycznego programisty to, czy język spełnia wszystkie kryteria określonej formalnej definicji „obiektowej” (wydaje się, że istnieje kilka konkurencyjnych!), Nie jest tak ważne, jak to, czy oferowane przez nią narzędzia są odpowiednie do myślenia o twój program pod względem wspomnianych obiektów - tj. faktycznie czerpiąc przypuszczalne korzyści OOP związane z produktywnością.

W C ++ obiekty są strasznie nieszczelnymi abstrakcjami, często zmuszając programistów do kłótni z nieprzyjemnymi problemami związanymi ze strukturą tych obiektów w pamięci - problemami bardziej przypominającymi kodowanie w prostym języku C niż w innych językach OOP. Na przykład C ++ Często zadawane pytania oferuje taką krytykę (między innymi):

Dla praktyka bardzo korzystne jest zapoznanie się z systemami OO innymi niż C ++ oraz z definicjami OO innymi niż trójca „enkapsulacji, dziedziczenia, polimorfizmu” interpretowanymi w specjalny sposób, umożliwiając uznanie C ++ za „OO”. Na przykład twierdzenie, że środowisko pozbawione sprawdzania granic lub wyrzucania elementów nie jest środowiskiem zewnętrznym, wydaje się oburzające dla osób przyzwyczajonych do C ++. Ale z wielu perspektyw ma to sens. Jeśli ktoś może zastąpić obiekt, to gdzie jest „enkapsulacja”? Jeśli usunięcie obiektu może prowadzić do wiszących odniesień lub wycieków pamięci, w jaki sposób system jest „obiektowy” ? Co powiesz na umiejętność określenia, jaki rodzaj obiektu znajduje się w danym miejscu i czasie? Mówisz, że oprogramowanie działa z obiektami - gdzie one są? A jeśli nie można się dowiedzieć, jak należy debugować oprogramowanie?

C ++ jest zorientowany obiektowo, ale nieprzyjemnie i niekompletnie: jego użytkownicy muszą poświęcić wiele wysiłku, aby upewnić się, że ich dane faktycznie zachowują się jak „prawdziwe” obiekty, a nie błędne bity. To powiedziawszy, wiele kodu zostało napisanych w C ++ przez cały okres jego życia, większość z nich korzysta z klas i dynamicznej wysyłki, więc jest to oczywiste coś, co można wykorzystać do praktycznego OOP.

Alex P.
źródło
-1 za odniesienie do FQA w odpowiedzi na poważną odpowiedź. FQA to gniazdo wypaczeń, półprawd i nieporozumień.
David Thornley,
@DavidThornley Czy ten cytat jest zniekształceniem, półprawdą lub nieporozumieniem?
Alex P
Gdzieś tam Twierdzenie, że język OO musi mieć sprawdzanie granic (czasem i tak wbudowane w standardowe kontenery C ++), a wyrzucanie elementów bezużytecznych (inteligentne wskaźniki to pierwotne zbieranie elementów bezużytecznych) jest wymuszone i nieuczciwe. Zdanie o języku, w którym wiszące odniesienia nie są zorientowane obiektowo, wyraźnie dowodzi Blatant Asercja. Zastanawia mnie „umiejętność określenia, jaki przedmiot”; typ wskaźnika oddaje go dla obiektów bez zachowania wirtualnego, a RTTI obsługuje go dla obiektów z zachowaniem wirtualnym.
David Thornley,
@DavidThornley Twierdzeniem FQA jest, że przydatny język OO powinien mieć takie rzeczy - co jest zgodne z zadawanym pytaniem (czy C ++ jest „odpowiedni”?). Myślę, że twierdzenie o definicjach gołych kości tak naprawdę nie odnosi się do tego ... „Zdolność do mówienia”: częste zachowanie błędu podczas uzyskiwania dostępu do obiektu, którego tak naprawdę nie ma, poprzez podążanie za wskaźnikiem do niektórych niezainicjowanych lub wcześniej nadpisanych danych; a twój program z przyjemnością weźmie te śmieci i zinterpretuje je jako dane, a następnie będzie podążał za wskaźnikami śmieci do innych danych śmieci, aż trafi na adres poza granicami lub wystąpi jakiś poważny błąd.
Alex P
Jednak cytat przynajmniej silnie sugerował twierdzenie, że język bez sprawdzania granic lub odśmiecania nie jest OO, i zignorował fakt, że masz takie rzeczy w C ++, jeśli chcesz. Pytanie, czy język zapobiega określonym klasom błędów, czy nie (z jakiegokolwiek powodu) jest ortogonalne w stosunku do tego, czy jest OO.
David Thornley,
-1

Jest powód, dla którego Graham Lee miał tutaj najwięcej pozytywnych opinii. Powtarzając, wydaje się, że klasa C ++ nie jest tak naprawdę obiektem w tym sensie, że nie wykonuje przekazywania wiadomości. Myślę, że to bardzo podoba ludziom, kiedy uczą się C ++ lub oop. Ludziom mówi się, że obiektowe jest „to”, a następnie mówi się, że C ++ robi to inaczej. C ++ nigdy nie robił inaczej OOP. Jeśli myślisz w ten sposób, nigdy nie docenisz klas C ++ za to, do czego są przeznaczone, a to dlatego, że stanowią jedynie ulepszenie paradygmatu proceduralnego poprzez włączenie abstrakcji i zachowania dynamicznego. Tak więc klasy C ++ są z zasady proceduralne, po prostu poprawiają paradygmat proceduralny, a raczej są bardziej zaawansowaną wersją struktury C.

irytująca kałamarnica
źródło
Czy masz jakieś uzasadnione powody dla swoich argumentów? Wydaje się, że robisz twierdzenia i twierdzisz, że ci, którzy się nie zgadzają, muszą się pomylić, lub zmieniliby zdanie, gdyby spojrzeli na to inaczej, a może gdyby podzielili twoją dokładną definicję OO.
David Thornley,
Słusznie. Możesz przeczytać ten artykuł . Wydaje mi się, że mówiłem, że c ++ nie jest „programowaniem obiektowym” w ścisłym sensie Alana Kaya. Jeśli jednak zdefiniujesz OOP jako strukturę danych z zachowaniem, możesz traktować c ++ jako OOP. Moim zdaniem bardziej trafne jest postrzeganie klasy c ++ jako abstrakcji programowania proceduralnego wyższego poziomu. Klasa c ++ jest znacznie wydajniejsza niż obiekt w stylu Kay, ale gorzej dla współbieżności. Osobiście uważam, że klasa c ++ to świetny projekt.
annoying_squid
1
Dzięki za link, ale wyjaśnia tylko, co Alan Kay miał na myśli. Ponadto nie zgadzam się, że Smalltalk jest ogólnie uważany za pierwszy język OO, a Wikipedia zgadza się ze mną, że była to Simula, jeden z dwóch języków Stroustrup połączonych w formę C z klasami. Interesuje mnie twoje twierdzenie, że klasa C ++ jest bardziej abstrakcyjnym programowaniem na wyższym poziomie niż szablon obiektowy, ale nadal nie rozumiem, dlaczego tak myślisz.
David Thornley,
Orientacja obiektu jest prawdopodobnie terminem subiektywnym, jeśli możemy się z tym zgodzić. Widzę jednak obiekt Kay jako bardziej naturalny sposób na rozdzielenie kodu i wprowadzenie współbieżnej modułowości w tym sensie, że każdy obiekt pełni rolę mini-komputerów oddziaływujących poprzez przekazywanie wiadomości. W ramach tego modelu między kodami b / c nie musi być żadnego kodu lub nie ma go wcale, cała logika programu może być wyrażona jako komórki i komunikaty. Dla porównania użycie „klas” zwykle wymaga między procedurami jakiegoś kodu kleju proceduralnego (brakuje prawdziwej modułowości), ale zaletą jest to, że klasy są znacznie wydajniejsze.
annoying_squid
-1

Steve Yegge powiedział najlepiej :

C ++ jest najgłupszym językiem na ziemi, w bardzo realnym sensie bycia najmniej świadomym. Nie wie o sobie.

System obiektu w C ++ jest tak ciężko przewodowych i stałe w czasie kompilacji, że to jest bardzo odległe od pierwotnego pojęcia OOP, który obejmuje wiadomości z pominięciem, introspekcji, refleksji, dynamiczny wysyłce i późne wiązanie, między innymi. Jedyne, co łączy C ++ i Smalltalk, to trochę słownictwa.

John Cromartie
źródło
W jaki sposób C ++ jest najmniej świadomym językiem? Co to znaczy, że język jest czuły? Jeśli masz na myśli, że brakuje mu możliwości odbijania, jest to dość powszechne i na pewno nie wybiera C ++ z tłumu.
David Thornley,
2
Jak, u licha, możesz powiedzieć, że powiedział to „najlepiej”? Nie mam pojęcia, co oznacza ten losowy cytat.
user16764
+1, mówiąc, że tego rodzaju rzeczy będą miały dużo błędów z basherów C ++, ale trzeba powiedzieć - nie można tak naprawdę OOP bez refleksji, ponieważ nie masz ogólnych możliwości zajmowania się poziomymi rzeczami ( aspekty) - cykl życia (aktywacja, usuwanie), ogólne zarządzanie błędami, ogólne proxy, ogólna serializacja, ogólna równoległość zadań - w końcu zanieczyszczają Twój kod i psują SoC.
vski
Dzięki. Nie mogę uwierzyć, że dostałem -3 za powiedzenie, że język bez refleksji nie jest dobrym przykładem OOP.
John Cromartie
1
@JohnCromartie, czy mógłbyś rozwinąć tę kwestię w swojej odpowiedzi?
Jeremy Heiler