Jakie są zalety programowania obiektowego w porównaniu z programowaniem proceduralnym?

77

Próbuję zrozumieć różnicę między językami proceduralnymi, takimi jak C, a językami obiektowymi, takimi jak C ++. Nigdy nie korzystałem z C ++, ale rozmawiałem z przyjaciółmi o tym, jak je rozróżnić.

Powiedziano mi, że C ++ ma koncepcje obiektowe, a także tryby publiczne i prywatne do definiowania zmiennych: rzeczy, których C nie ma. Nigdy nie musiałem ich używać do tworzenia programów w Visual Basic.NET: jakie są z tego korzyści?

Powiedziano mi również, że jeśli zmienna jest publiczna, można uzyskać do niej dostęp w dowolnym miejscu, ale nie jest jasne, jak różni się ona od zmiennej globalnej w języku takim jak C. Nie jest również jasne, w jaki sposób zmienna prywatna różni się od zmiennej lokalnej.

Inną rzeczą, którą usłyszałem, jest to, że ze względów bezpieczeństwa, aby uzyskać dostęp do funkcji, należy ją najpierw odziedziczyć. Przypadek użycia polega na tym, że administrator powinien mieć tylko tyle praw, ile potrzebuje, a nie wszystko, ale wydaje się, że warunek też by działał:

if ( login == "admin") {
    // invoke the function
}

Dlaczego to nie jest idealne?

Biorąc pod uwagę, że wydaje się, że istnieje proceduralny sposób wykonywania wszystkiego zorientowanego obiektowo, dlaczego miałbym się przejmować programowaniem obiektowym?

niko
źródło
11
Ta mapa paradygmatów programowania może ci pomóc.
AProgrammer
26
+1, aby odeprzeć niektóre negatywne opinie. Gdyby współpracownik zadał mi takie pytanie, prawdopodobnie miałbym pewne obawy i mógłbym nawet głosować za nim (zakładając, że obok niego znajdowała się jakaś strzałka skierowana w dół). Wydaje się jednak, że pytanie to zadaje przyszły inżynier oprogramowania i wygląda na to, że poświęcił trochę czasu na przemyślenie i omówienie tematu przed opublikowaniem. Głosuję za udzieleniem mu pomocy, a nie zwolnieniem.
DXM,
14
@DXM Doskonały pomysł! Strzałki w dół / w górę unoszące się wokół współpracowników ... To działałoby cuda.
yannis
2
Standardowy argument przeciwny: Istnieje również sposób asemblera na zrobienie wszystkiego, co możesz zrobić w C, więc dlaczego miałbyś przejmować się C? (Wskazówka: Chodzi o podniesienie poziomu abstrakcji. C ++ udaje się to zrobić bez poświęcania większości prędkości C. IMO jest głównym powodem sukcesu C ++.)
sbi 16.11.11

Odpowiedzi:

135

Wszystkie dotychczasowe odpowiedzi koncentrowały się na temacie twojego pytania, jak stwierdzono: „jaka jest różnica między c i c ++”. W rzeczywistości wygląda na to, że wiesz, czym jest różnica, po prostu nie rozumiesz, dlaczego taka różnica jest potrzebna. Zatem inne odpowiedzi próbowały wyjaśnić OO i enkapsulację.

Chciałem odpowiedzieć na jeszcze jedną odpowiedź, ponieważ na podstawie szczegółów twojego pytania uważam, że musisz cofnąć się o kilka kroków.

Nie rozumiesz celu C ++ lub OO, ponieważ wydaje ci się, że Twoja aplikacja po prostu musi przechowywać dane. Te dane są przechowywane w zmiennych. „Dlaczego miałbym chcieć, aby zmienna była niedostępna? Teraz nie mam już do niej dostępu! Dzięki upublicznieniu wszystkiego, a jeszcze lepiej globalizacji, mogę czytać dane z dowolnego miejsca i nie ma żadnych problemów”. - I masz rację, biorąc pod uwagę skalę projektów, które obecnie piszesz, prawdopodobnie nie ma tak wielu problemów (lub jest ich, ale po prostu jeszcze ich nie zauważyłeś).

Myślę, że podstawowe pytanie, na które naprawdę musisz odpowiedzieć, brzmi: „Dlaczego miałbym kiedykolwiek chcieć ukryć dane? Jeśli to zrobię, nie będę w stanie z tym pracować!” I dlatego:

Załóżmy, że zaczynasz nowy projekt, otwierasz edytor tekstu i zaczynasz pisać funkcje. Za każdym razem, gdy musisz coś zapisać (aby zapamiętać na później), tworzysz zmienną. Aby uprościć sprawę, zmienne są globalne. Twoja pierwsza wersja Twojej aplikacji działa świetnie. Teraz zaczynasz dodawać więcej funkcji. Masz więcej funkcji, niektóre dane, które wcześniej zapisałeś, muszą zostać odczytane z nowego kodu. Inne zmienne wymagają modyfikacji. Ciągle piszesz więcej funkcji. To, co mogłeś zauważyć (a jeśli nie, to absolutnie zauważysz w przyszłości), to fakt, że w miarę powiększania się kodu, dodanie kolejnej funkcji zajmuje coraz więcej czasu. W miarę powiększania się kodu, coraz trudniej jest dodawać funkcje bez zepsucia czegoś, co kiedyś działało. Dlaczego? Ponieważ musisz pamiętać, co wszystkotwoje zmienne globalne są przechowywane i musisz pamiętać, gdzie wszystkie są modyfikowane. I musisz pamiętać, która funkcja jest w porządku, aby wywoływać w dokładnej kolejności, a jeśli wywołasz je w innej kolejności, możesz otrzymać błędy, ponieważ twoje zmienne globalne nie są jeszcze poprawne. Czy kiedykolwiek na to wpadłeś?

Jak duże są twoje typowe projekty (wiersze kodu)? Teraz obrazuje projekt 5000 do 50000 razy większy niż twój. Ponadto pracuje w nim wiele osób. Jak wszyscy członkowie zespołu mogą pamiętać (a nawet być świadomi) tego, co robią wszystkie te zmienne?

To, co opisałem powyżej, jest przykładem doskonale sprzężonego kodu. A od zarania dziejów (zakładając, że czas zaczął się 1 stycznia 1970 r.) Ludzkość szuka sposobów na uniknięcie tych problemów. Aby tego uniknąć, należy podzielić swój kod na systemy, podsystemy i komponenty oraz ograniczyć liczbę funkcji mających dostęp do dowolnej części danych. Jeśli mam 5 liczb całkowitych i ciąg znaków reprezentujący pewien stan, czy łatwiej byłoby mi pracować z tym stanem, gdyby tylko 5 funkcji ustawiło / otrzymało wartości? lub jeśli 100 funkcji ustawia / otrzymuje te same wartości? Nawet bez języków OO (tj. C) ludzie ciężko pracowali nad izolowaniem danych od innych danych i tworzeniem czystych granic separacji między różnymi częściami kodu. Gdy projekt osiągnie określony rozmiar, łatwość programowania staje się niemożliwa: „czy mogę uzyskać dostęp do zmiennej X z funkcji Y”,

Właśnie dlatego wprowadzono koncepcje OO i dlatego są tak potężne. Pozwalają ukryć twoje dane przed sobą i chcesz to zrobić celowo, ponieważ im mniej kodu widzi te dane, tym mniejsza szansa, że ​​kiedy dodasz następną funkcję, coś zepsujesz. Jest to główny cel koncepcji enkapsulacji i programowania OO. Pozwalają rozbić nasze systemy / podsystemy na jeszcze bardziej szczegółowe pola, do tego stopnia, że ​​bez względu na to, jak duży jest cały projekt, do danego zestawu zmiennych można uzyskać dostęp tylko za pomocą 50-200 linii kodu i to wszystko! Programowanie OO ma oczywiście znacznie więcej, ale w gruncie rzeczy właśnie dlatego C ++ oferuje opcje deklarowania danych / funkcji jako prywatne, chronione lub publiczne.

Drugim największym pomysłem w OO jest koncepcja warstw abstrakcji. Chociaż języki proceduralne mogą mieć również abstrakcje, w C programista musi podjąć świadomy wysiłek, aby utworzyć takie warstwy, ale w C ++, kiedy deklarujesz klasę, automatycznie tworzysz warstwę abstrakcji (to nadal zależy od tego, czy ta abstrakcja będzie, czy nie) doda lub usunie wartość). Powinieneś przeczytać / zbadać więcej na temat warstw abstrakcji, a jeśli masz więcej pytań, jestem pewien, że to forum z przyjemnością na nie odpowie.

DXM
źródło
5
Świetna odpowiedź, wydaje się trafiać na odpowiedni poziom, biorąc pod uwagę pytanie
Carlos
29
+1 ... głównie dla linii „I od zarania
dziejów
4
@Chad - Pomyślałem, że sama linia powinna zdobyć co najmniej jeden punkt :)
DXM
Istnieje sposób radzenia sobie z problemem skali, o którym mówisz w paradygmacie proceduralnym. To się nazywa funkcje. Ale dobry sposób na wyjaśnienie problemu.
annoying_squid
@DXM - Nie jestem pewien, czy poprawnie zrozumiałem odpowiedź. Możemy również osiągnąć tę samą funkcjonalność ustawiania / uzyskiwania w Programowaniu proceduralnym. Możemy napisać funkcje set / get w C, aby zmodyfikować / uzyskać zmienną globalną. Korzystając z tej metody, ograniczamy także liczbę funkcji modyfikujących zmienne globalne. I nawet w OOP, jeśli użyjemy metod set / get, będziemy używać tych metod spoza obiektu do zmiany wartości.
kadina
10

Hmm ... może najlepiej jest wykonać kopię zapasową i spróbować przedstawić podstawowe założenia programowania obiektowego. Programowanie obiektowe w dużej mierze ma na celu umożliwienie tworzenia abstrakcyjnych typów danych. Dla naprawdę prostego przykładu, z którym jesteś niewątpliwie zaznajomiony, rozważ ciąg. Łańcuch zwykle ma bufor do przechowywania zawartości łańcucha, niektóre funkcje, które mogą działać na łańcuchu (wyszukiwanie w nim, uzyskiwanie dostępu do jego części, tworzenie podciągów itp.) Będzie także (przynajmniej zwykle) coś do śledź (bieżącą) długość łańcucha i (prawdopodobnie) rozmiar bufora, więc jeśli (na przykład) zwiększysz rozmiar łańcucha z 1 do 1000000, będzie wiedział, kiedy potrzebuje więcej pamięci, aby pomieścić większy zawartość.

Te zmienne (bufor, aktualna długość i rozmiar bufora) są prywatne do samego łańcucha, ale oni nie lokalne dla danej funkcji. Każdy ciąg ma treść o określonej długości, dlatego musimy śledzić jego treść / długość dla tego ciągu. I odwrotnie, ta sama funkcja (np. W celu wyodrębnienia podłańcucha) może działać na wielu różnych ciągach w różnych momentach, więc dane nie mogą być lokalne dla poszczególnych funkcji.

W rezultacie otrzymujemy pewne dane prywatne dla łańcucha, więc są one (bezpośrednio) dostępne dla funkcji łańcucha. Świat zewnętrzny może uzyskać długość łańcucha za pomocą funkcji łańcucha, ale nie musi nic wiedzieć o wewnętrznych elementach łańcucha, aby go uzyskać. Podobnie, może modyfikować ciąg - ale znowu robi to za pomocą funkcji ciągu i tylko one bezpośrednio modyfikują te zmienne lokalne dla obiektu ciągu.

Jeśli chodzi o bezpieczeństwo, zauważę, że chociaż jest to rozsądne jako analogia, nie tak to działa. W szczególności dostęp w C ++ nie ma na celu spełnienia tego samego rodzaju wymagań co dostęp w systemie operacyjnym. System operacyjny powinien egzekwować ograniczenia, aby (na przykład) normalny użytkownik nie mógł robić rzeczy zarezerwowanych dla administratora. Natomiast kontrola dostępu w C ++ ma na celu wyłącznie zapobieganie wypadkom. Z założenia każdy, kto chce je łatwo ominąć. Są w tej samej kolejności, co oznaczanie pliku jako tylko do odczytu, więc nie można go przypadkowo usunąć. Jeśli zdecydujesz się usunąć plik, zmiana go z trybu tylko do odczytu na tryb do odczytu i zapisu jest banalna; ustawienie na „tylko do odczytu” powoduje, że przynajmniej pomyślisz o tym przez sekundę i zdecydujesz się usunąć plik, aby nie został przypadkowo usunięty po uderzeniu niewłaściwego klucza w niewłaściwym czasie.

Jerry Coffin
źródło
6

OOP kontra C tak naprawdę nie dotyczy żadnej z omawianych kwestii. Chodzi przede wszystkim o pakowanie kodu w obszary, które nie wpływają / nie mogą przypadkowo (a czasem nawet celowo) na siebie wpływać.

C pozwala w zasadzie uruchomić dowolną funkcję z dowolnego miejsca. OOP zapobiega temu poprzez grupowanie metod w klasy i zezwalanie na korzystanie z metod tylko przez odwołanie się do klasy je zawierającej. Tak więc jedną potencjalnie dużą zaletą OOP jest to, że znacznie bardziej prawdopodobne jest, że będziesz mieć lepszą aranżację kodu bez dużego doświadczenia, aby powiedzieć, że powinieneś.

John Fisher
źródło
4
-1. W C nie ma nic wyłącznego, co czyni wszystkie funkcje globalnymi. Możesz zadeklarować dowolną funkcję statyczną i tym samym ograniczyć jej zakres do pliku lokalnego. Pod tym względem C nie różni się od C ++, Java itp. Ponadto OOP nie dotyczy składni językowej, możesz pisać programy OO w C w porządku, chociaż będą one nieco bardziej surowe niż w językach z obsługą składni OO. Przeciwnie: nie dostajesz OOP tylko dlatego, że wybrałeś język, który obsługuje OO. Orientacja obiektowa to styl programowania , a nie funkcja języka.
@Lundin: Chociaż technicznie masz rację, nie trafiłeś w sedno. Języki OOP domyślnie zachowują się w sposób OOP. C nie.
John Fisher
1
W językach OO nic nie zmusza do tego. Na przykład widziałem niezliczoną liczbę niejasnych programów w C ++, o których nie warto wspominać. Podobnie, jeśli nie masz pojęcia o OO, ale próbujesz wdrożyć klasy, dziedzictwo itp., Istnieje około 100% szansy na stworzenie pomieszanego programu.
@Lundin: Nie sądzę, że C ++ jest dobrym przykładem. Ma (lub przynajmniej miała) być w stanie kompilować programy C bez (znacznych) modyfikacji. Dodanie klas na górze nie czyni z niego języka OOP na poziomie C # lub Java, ale umożliwia taki rozwój.
John Fisher,
Możesz pisać programy inne niż OO w Javie, po prostu włamać się do jednego ogromnego głównego pliku ... OO nadal nie jest specyficzne dla języka, jeśli programista nie wie o OO, żaden język na świecie ich nie uratuje.
4

Dobrze napisana klasa powinna być małą „wyspą zaufania”: możesz jej użyć i założyć, że robi to „właściwą rzecz” i że chroni cię przed typowymi pułapkami. To sprawia, że ​​dobra klasa jest elementem składowym, który jest o wiele bardziej przydatny jako zestaw funkcji i zmiennych, które mogą działać dobrze, ale pokazują wszystkie ich brzydkie odwagi i zmuszają cię do zrozumienia, jak działają razem, jak należy je inicjalizować itp. Dobra klasa powinna być jak wtyczka USB, podczas gdy rozwiązanie proceduralne jest jak wiązka drutów, chipów, cyny i bitu lutowniczego.

Jednym z zagadnień, które nie zostały szczegółowo omówione, jest aspekt interfejsu / implementacji. Interfejs opisuje zachowanie, ale nie realizację. Interfejs listy opisuje tę koncepcjęlisty i jej zachowanie: można się spodziewać metod dodawania, usuwania i określania rozmiaru. Obecnie istnieje wiele różnych sposobów implementacji tej listy, np. Jako lista połączona lub przy użyciu bufora tablicy. Moc programowania OO polega na tym, że za pomocą interfejsu możesz rozumować zachowanie bez wiedzy o implementacji. Uzyskiwanie dostępu do wewnętrznych zmiennych lub metod zniszczyłoby tę abstrakcję, nie można zastąpić jednej implementacji listy inną i nie można ulepszyć istniejącej implementacji bez dotykania kodu za pomocą klasy. To jeden z głównych powodów, dla których potrzebne są prywatne zmienne i metody: aby chronić wewnętrzne szczegóły implementacji, aby abstrakcja pozostała nienaruszona.

OO idzie o krok dalej: np. W przypadku bibliotek możesz zdefiniować interfejs dla rzeczy, które jeszcze nie istnieją , i napisać kod, który będzie działał z tym interfejsem. Użytkownicy mogą pisać klasy implementujące interfejs i korzystać z usług udostępnianych przez bibliotekę. Pozwala to na pewien stopień elastyczności, który nie jest możliwy w przypadku programowania proceduralnego.

Landei
źródło
Koncepcja interfejsów nie jest unikalna dla języków obiektowych. Myślę, że większym czynnikiem jest to, że w językach innych niż OOP prawie wszystkie funkcje używane w module muszą należeć do tej samej globalnej przestrzeni nazw. Wymaga to, aby jedna z nazw funkcji prefiksu wskazywała, na co działa, lub mieć wiele podobnie brzmiących metod, które robią zupełnie inne rzeczy (np. SetLocationMożna użyć do przesunięcia a Monster, a do SetPositionprzesunięcia a PopupWindow, i Movemożna użyć do regulacji pozycji z DisplayCursor). Próbowanie znaleźć właściwą metodę „ruchu” ...
supercat
... może być znacznie łatwiejsze, jeśli podczas pisania MyMonstor->edytor pokazuje tylko listę metod, które można zastosować do rzeczy typu Monster. Jeśli istnieje wiele tuzinów różnych rzeczy, z których każda obsługuje około tuzina operacji, zmniejszenie bałaganu na listach metod o 90% może znacznie zmniejszyć wydajność.
supercat
Zderzenie nazw @supercat to problem językowy, a nie problem niezwiązany z OOP. Z drugiej strony przestrzenie nazw są problematyczne, ponieważ kompilator zasadniczo musi automatycznie zmienić nazwę funkcji lub zmienić jej orientację. Dlaczego więc nie zrobić tego ręcznie?
annoying_squid
@annoying_squid: OOP zapewnia możliwość efektywnego wykorzystania rodzaju głównego argumentu funcitona do wybrania przestrzeni nazw. Jeśli mam zmienną ittypu SuperFancyWhizBang, wywołanie jednej z SuperFancyWhizBangmetod itnie wymaga zapisania typu SuperFancyWhizBang; powiedzenie it.woozle()sprawi, że kompilator automatycznie wyszuka woozlewewnątrz SuperFancyWhizBang.
supercat
3

Istnieje sposób na zrobienie wszystkiego za pomocą maszyny Turinga lub co najmniej w języku asemblera dla kodu maszynowego, do którego ostatecznie skompiluje program C lub C ++.

Różnica nie polega więc na tym, co może zrobić kod, ale na tym, co ludzie mogą zrobić.

Ludzie popełniają błędy. Wiele.

OOP wprowadza paradygmat i składnię, która pomaga zmniejszyć rozmiar i gęstość prawdopodobieństwa przestrzeni możliwych błędów kodowania przez człowieka. Czasami czyniąc błąd niezgodnym z prawem dla określonej klasy obiektu danych (np. Nie jest to metoda zadeklarowana dla tego obiektu). Czasami popełniając błąd bardziej gadatliwie lub dziwnie wyglądając stylistycznie w porównaniu do kanonicznego użycia języka. Czasami wymagając interfejsu o znacznie mniej możliwych niespójnych lub zaplątanych zastosowaniach (publicznych lub prywatnych). itp.

Im większy projekt, tym większe prawdopodobieństwo błędów. Na który nowy program kodujący może nie być narażony, jeśli ma do czynienia z małymi programami. Zatem potencjalne zagadnienie, dlaczego OOP jest cenne.

hotpaw2
źródło
2

Twoje pytanie wydaje się bardziej na temat celu OOP niż różnicy. Koncepcja w twoim poście to Encapsulation; i istnieje enkapsulacja wspierająca ZMIANĘ. Kiedy inne klasy uzyskują dostęp do twoich wewnętrznych elementów, trudno jest je modyfikować bez ich łamania. W OOP udostępniasz interfejs (członkowie publiczni), przez który pozwalasz innym klasom na interakcję z twoim, a także ukrywasz swoje elementy wewnętrzne, aby można je było bezpiecznie zmienić.

Eoin Carroll
źródło
Wystarczy użyć prototypów funkcji. To jest kapsułkowanie.
annoying_squid
2

Bez względu na to, gdzie czytam, nie można uzyskać dostępu do zmiennych prywatnych, podczas gdy zmienne publiczne mogą być więc dlaczego nie upublicznić jako globalne, a prywatne jako lokalne, jaka jest różnica? jaki jest prawdziwy użytek publiczny i prywatny? proszę nie twierdzić, że może być używany przez wszystkich. Przypuszczam, że dlaczego nie korzystamy z pewnych warunków i wykonujemy połączenia?

Mam nadzieję, że nigdy nie chcesz więcej niż jednego ciągu w swojej aplikacji. Mam również nadzieję, że zmienne lokalne będą się utrzymywać między wywołaniami funkcji. Te rzeczy mogą być takie same pod względem dostępności, ale pod względem żywotności i innych zastosowań? Nie są absolutnie takie same.

DeadMG
źródło
1

Jak wielu mówi, każdy program po skompilowaniu jest zamieniany na kod binarny, a ponieważ ciąg binarny może być użyty do przedstawienia liczby całkowitej, każdy program jest w końcu tylko liczbą. Jednak zdefiniowanie potrzebnej liczby może być dość trudne i dlatego pojawiły się języki programowania wysokiego poziomu. Języki programowania są tylko modelami kodu asemblera, który ostatecznie produkują. Chciałbym wyjaśnić wam różnicę między programowaniem proceduralnym a OO za pomocą tego bardzo ładnego artykułu na temat programowania kontekstowego http://www.jot.fm/issues/issue_2008_03/article4/

jak widać na tym obrazie, przedstawionym w artykule, programowanie proceduralne zapewnia tylko jeden wymiar do powiązania jednostki obliczeniowej z nazwą. W tym przypadku wywołania procedur lub nazwy są bezpośrednio mapowane na implementacje procedur. Na rysunku wywołanie m1 nie pozostawia innego wyboru niż wywołanie jedynej implementacji procedury m1.

Programowanie obiektowe dodaje kolejny wymiar rozpoznawania nazw do programowania proceduralnego. Oprócz nazwy metody lub procedury wysyłanie komunikatów uwzględnia odbiornik komunikatów podczas wyszukiwania metody. Na ryc. B widzimy dwie implementacje metody m1. Wybór odpowiedniej metody zależy nie tylko od nazwy wiadomości m1, ale także od odbiorcy faktycznej wiadomości, tutaj Ry.

To rzeczywiście umożliwia enkapsulację i modularyzację.

wprowadź opis zdjęcia tutaj

Rysunek c dotyczy wreszcie programowania zorientowanego na przedmiot, który rozszerza zorientowanie obiektowe o kolejny wymiar.

Mam nadzieję, że pomogło ci to myśleć w OOP z innej perspektywy.

Silli
źródło
0

(+1) Pytanie o coś, czego nie rozumiesz, jest dobre, nawet jeśli brzmi głupio.

Różnica polega na programowaniu obiektowym i klasowym. „Plain C”, działa z danymi i funkcjami. „C ++” dodaje pojęcia „obiekt i klasy” oraz kilka powiązanych pojęć wtórnych.

Jednak zalecam programistom nauczenie się „Plain C” przed „C ++”. Lub „Procedural Pascal” przed „Object Pascal”.

Wielu programistów uważa, że ​​uczniowie powinni uczyć tylko jednej rzeczy.

Na przykład, starzy nauczyciele, którzy nie otrzymują OO i uczą tylko „Plain Structured C”.

Lub „hipsterowi” nauczyciele, którzy uczą tylko OO, ale nie „Plain C”, ponieważ „nie potrzebujesz go”. Lub oba, bez dbania o porządek nauczania.

Raczej uważam, że uczniowie powinni uczyć się zarówno „Structured Plain C”, jak i „Object Oriented C (C ++)”. Najpierw „Plain C” i „C ++”.

W prawdziwym świecie musisz nauczyć się obu paradygmatów (oraz innych paradygmatów, takich jak „funkcjonalny”).

Pomóc może myślenie o ustrukturyzowanych programach jako dużym, pojedynczym „obiekcie”.

Powinieneś także położyć nacisk na przestrzenie nazw („moduły”), w obu językach wielu nauczycieli po prostu to ignoruje, ale to ważne.

umlcat
źródło
Przestrzenie nazw i przeciążenia tylko utrudniają zrozumienie programu. Sprawia, że ​​proces identyfikacji jest wrażliwy na kontekst. Gdy widzisz foo()w C ++, może to być funkcja globalna, funkcja w bieżącej przestrzeni nazw, funkcja w przestrzeni nazw, której używasz using, metoda, metoda dziedziczona, a jeśli jest w wywołaniu funkcji: może to być przestrzeń nazw, która można rozwiązać za pomocą wyszukiwania nazw na podstawie argumentów, podobnie jest w przypadku Java i C #. W C może to być tylko funkcja statyczna w bieżącym pliku źródłowym lub jedna z nagłówka.
Calmarius
Pisanie MODULE_Foo () wszędzie może być bałaganem wizualnym, ale przynajmniej dokładnie wiesz, która to funkcja.
Calmarius
@Calmarius rozwiązaniem jest oczywiście nie wymieniać niczego foo .
0

Jednym słowem, zarządzanie projektami. Chodzi mi o to, że C ++ pomaga mi egzekwować zasady używania mojego kodu przez innych. Pracując nad projektem o wartości 5,5 miliona linii programowanie obiektowe jest bardzo pomocne. Kolejną zaletą jest kompilator, który zmusza mnie (i wszystkich innych) do przestrzegania pewnych zasad i wychwytywania drobnych błędów w czasie kompilacji. Są też wszystkie teoretyczne zalety, ale chciałem skupić się na codziennych praktycznych rzeczach. W końcu wszystko to kompiluje się w kod maszynowy.

Gus
źródło
-1

Programowanie obiektowe to Programowanie proceduralne z ramkami.

W PP masz jedno pudełko, jeden stan, który staje się niewiarygodnie duży w miarę rozwoju projektu, powodując pojawienie się efektów ubocznych za każdym razem, gdy zapomnisz trochę tego dużego stanu.

W OO masz wiele skrzynek, wiele stanów, a wraz z rozwojem projektu, pudełka trochę rosną, a liczba pudeł rośnie.

Łatwiej jest patrzeć na mniejsze pudełka, łatwo mieć iluzję całego obrazu, ale w rzeczywistości prawie niemożliwe, ponieważ patrząc na klasy i interfejsy ukrywa się szczegóły implementacji, które mogą mieć ważne konsekwencje.

W programowaniu funkcjonalnym masz wiele pól funkcyjnych i decydujesz, że każda funkcja ma jeden wpis (parametry) i jedno wyjście (powrót), bez żadnego innego dostępu do kontekstu zewnętrznego.

Ponieważ nie ma stanu i efektów ubocznych (zgodnie z projektem), możesz bezpiecznie analizować dowolną funkcję oddzielnie od całości i wiedzieć w 100%, jak będzie się zachowywać w każdych okolicznościach.

Ponieważ kodujesz kodowanie według jednostek logicznych reprezentujących akcje, możliwe jest również posiadanie tylko jednego pola na typowe działanie.

Spowoduje to zmniejszenie kodu dowolnego projektu na dużą skalę w porównaniu do OOP, który promuje ukrywanie wielu funkcji analogowych w całej bazie kodu w różnych klasach.

To również znacznie przekroczy PP, ponieważ możesz rozwijać projekt znacznie dłużej, ponieważ nie ma już stanu XXXXXXXL do śledzenia.

Podsumowując, PP jest prawdopodobnie najprostszym sposobem podejścia do prostego programu, a FP jest prawdopodobnie najprostszym sposobem podejścia do złożonego.

Jeśli weźmiesz pod uwagę cel ujednolicenia wszystkich baz kodu i poprawy ponownego wykorzystania kodu, zawsze należy stosować FP, ponieważ jest to jedyny paradygmat, który ma sens na bardzo dużą skalę, a także jedyny paradygmat, który ma 100% możliwości ponownego użycia (możesz po prostu skopiuj wklej funkcję i użyj jej gdzie indziej, bez żadnych narzutów).

Otrzymujesz w 100% niezawodne testy jednostkowe za darmo.

I nie musisz pisać „prywatny statyczny finał genialnego genialnego niesamowitego ciągu_1”.

I dostajesz równoległość za darmo.

Morg.
źródło
-3

Prosta różnica w jednym zdaniu polega na tym, że C ++ to C z klasami (choć teraz jest o wiele więcej). Nie rozumiem, dlaczego nie chcesz poznać różnic między dwoma, czytając świetny artykuł na temat C ++ na Wikipedii .... .Ten artykuł bardzo ci pomoże: - C ++ (Wikipedia)

Pomocne będzie także wyszukiwanie go w Google. Poproszenie przypadkowych osób o wyjaśnienie tego może być trudne. IMHO lepiej rozumie się czytając niż pytając kogoś

Pankaj Upadhyay
źródło
Przeczytałem je, ale powiedzieli tylko, gdzie są używane, ale wciąż nie rozwiązałem mojego pytania.
niko
Nie zadałem pytania, nie wkładając żadnych wysiłków w wyszukiwarkę Google, ale wciąż nie rozumiem różnicy, więc spotkałem się z przepełnieniem stosu, aby mi w tym pomóc
niko,
1
@niko, źle mnie tutaj rozumiesz. Miałem na myśli to, że powinieneś spróbować zrozumieć różnicę między nimi, czytając. Pytanie znajomych nie jest dobre. Ponieważ zapewnią własne zrozumienie, które może cię nie nasycić. Ale nie martw się, są tutaj wspaniali rówieśnicy, na pewno ci pomogą :-)
Pankaj Upadhyay
2
Nie głosowałem za bardzo, ale bardzo kusiło mnie „C ++ is C with Classes”. Ci z nas, którzy mogą faktycznie C ++ działają nasze tyłki próbując że na głowy ludzi.
DeadMG
1
@Pankaj: Zgadza się. To było C z klasami. Zdecydowanie nie jest to już C z klasami, a nazywanie go takim jest prawie 30 lat nieaktualne. Od tego czasu C ++ przeszedł bardzo długą drogę. Ludzie, którzy teraz kodują C ++, nigdy nie odnoszą się do tego w ten sposób. Zachęca do najgorszych nawyków i złego wrażenia.
DeadMG