Jakie są podstawowe różnice między C i C ++? [Zamknięte]

41

Wiele osób pisze „C / C ++”, jakby to było to samo. Chociaż mają wiele podobieństw, najwyraźniej nie są takie same.

Ale jakie są naprawdę podstawowe różnice między C i C ++? Czy C ++ jest ulepszoną wersją C, czy też są funkcje w C, które nie istnieją w C ++?

gablin
źródło
2
Myślałem, że C ++ to super zestaw C
użytkownik
1
C ++ nie jest ulepszony ... jest nadzbiorem C ..
Joe DF
2
@JoeDF To było na samym początku, ale tak naprawdę jest teraz „kompatybilne z C”, co wcale nie znaczy tego samego. Nie kodujesz w C w C ++ i nie wszystkie standardowe C są kompatybilne ze standardowym C ++.
Klaim
+1 Masz rację, są teraz tacy jak bracia lub kuzyni. Jeśli wiesz co mam na myśli.
Joe DF,

Odpowiedzi:

43

Następujące punkty dotyczą C ++:

  1. (zdefiniowany przez użytkownika) system typu statycznego: umożliwia kontrolę statyczną twoich danych i ich wykorzystania - wskazuje wiele łatwych do wykonania błędów w C.
  2. multi- „paradygmat”: umożliwia pracę jak w C, z paradygmatami obiektowymi, z paradygmatami ogólnymi itp.
  3. Constructor / Destructor: jedyny sposób, aby powiedzieć raz, co robić podczas tworzenia lub niszczenia czegoś i mieć pewność, że użytkownik nie będzie musiał znaleźć właściwej funkcji i używać jej jak w C.
  4. RAII (źle nazwane): nie zawsze musisz zarządzać pamięcią. Po prostu trzymaj wszystko w zasięgu i używaj inteligentnych wskaźników opisujących żywotność twoich obiektów. Nadal można używać surowych wskaźników.
  5. Szablony: lepszy niż makro, prawdziwy język do manipulowania i generowania typów przed ostateczną kompilacją. Brakuje tylko systemu typów (patrz Pojęcia w przyszłych standardach C ++).
  6. Przeciążenie operatora: pozwala opisać operacje w prosty sposób składniowy, a nawet zdefiniować języki specyficzne dla domeny w kodzie C ++.
  7. Nazwy o zasięgu: przestrzenie nazw, klasy / struktura, funkcje itp. Mają proste reguły, aby upewnić się, że nazwy się nie kolidują.
  8. System wyjątków: sposób propagowania błędów, który jest często lepszy niż kod powrotu. W rzeczywistości kod powrotu jest odpowiedni dla błędów logicznych specyficznych dla domeny, ponieważ aplikacja musi nim zarządzać. Wyjątek stanowią „twarde” błędy, które powodują, że poniższy kod jest po prostu niepoprawny. Pozwala to na wychwytywanie błędów wyżej w stosie wywołań, jeśli to możliwe, reagowanie na taki wyjątek (przez rejestrowanie lub ustalanie stanu), a przy RAII, jeśli jest dobrze używany, nie powoduje to błędu całego programu - jeśli zrobi się to dobrze, ponownie.
  9. Biblioteka standardowa: C ma swoją własną, ale jest „dynamiczna”. Standardowa biblioteka C ++ jest prawie (nie strumieni IO) wykonana z szablonów (kontenerów i algorytmów), które pozwalają generować kod tylko dla tego, czego używasz. Lepiej: ponieważ kompilator musi generować kod, będzie dużo wiedział o kontekście i na szczęście zastosuje wiele optymalizacji bez konieczności kodera zaciemniania kodu - dzięki szablonom i innym rzeczom.
  10. const-correctness: Najlepszy sposób, aby upewnić się, że nie zmienisz zmiennych, których nie powinieneś. Pozwala określić dostęp tylko do odczytu do zmiennych. I jest sprawdzane tylko w czasie kompilacji, więc nie ma żadnych kosztów w czasie wykonywania.
Klaim
źródło
31

C ++ został opracowany w celu zarządzania złożonością, z którą C nie mógł sobie poradzić. Na przykład częstym problemem w C było to, że można „zabraknąć nazw zmiennych” (nie należy tego rozumieć dosłownie), ponieważ nie było enkapsulacji, przestrzeni nazw itp.

Ponadto C nie ma wyjątków, dlatego obsługa błędów jest bardzo podatna na błędy, ponieważ to od użytkownika biblioteki zależy zawsze sprawdzanie zwracanych wartości func, podczas gdy z wyjątkami, twórca biblioteki po prostu zgłasza wyjątek, który gwarantuje, że przepływ programu zostanie zatrzymany.

C ++ pomaga, mając obiekty inicjujące konstruktora, które są automatycznie wywoływane przez kompilator. W przeciwieństwie do struktur C, które muszą zostać zainicjowane przez programistę (stąd inny obszar podatny na błędy).

Wreszcie, OOP ma wiele innych zalet, takich jak ponowne wykorzystanie obiektów, a także ogólne koncepcje oparte na programowaniu, takie jak szablony i ogólne, które pozwalają na ponowne użycie kodu źródłowego itp.

I wiele innych rzeczy, których wymienienie zajęłoby zbyt wiele czasu.

Jas
źródło
Podoba mi się, że piszesz o konstruktorze C ++ vs strukturach C i że jest podatny na błędy. Zgadzam się z tym. Ale nie podoba mi się sposób korzystania z Java w JavaBeans, który zawsze używa pustego konstruktora, a następnie ustawia pola składowe za pomocą ustawiaczy. Moim zdaniem jest to podatne na błędy jak struktury C. Wolałbym ustawiać moje obiekty Java tylko za pomocą konstruktora. Zobacz moje pytanie na temat StackOverflow na ten temat.
Jonas
Masz rację, ale w centrum mojej odpowiedzi było C vs. C ++.
Jas
1
Och, daj spokój, kto uniemożliwia ci używanie OOP z C? Możesz ponownie wykorzystywać przedmioty i robić wszystko, nawet wyjątki. Jest nawet książka na ten temat, zwana programowaniem OOP w C.
2
@Vlad, nic z tego, o czym mówisz, nie było opcją 25 lat temu.
Jas
4
MOŻESZ robić OOP w prawie każdym używanym języku programowania, ale to nie znaczy, że język został zaprojektowany do tego. Weźmy na przykład Luę. Chociaż technicznie pozwala to na OOP, wydaje się, że istnieje około pięćdziesięciu różnych sposobów na zrobienie tego, co powoduje wiele bólu głowy.
tyjkenn
15

Ogólnie wszystko, co istnieje w C, jest obsługiwane w C ++. Oczywiście odwrotność jest absolutnie fałszywa.

Mówiąc wprost, C ++ jest zorientowany obiektowo (więc na przykład masz klasy), C nie.

C ++ ma typ boolowski, którego nie ma C89.

Są to różne języki. Po prostu dzielą większość składni.

Federico klez Culloca
źródło
4
C99 ma logiczną typu (o nazwie _Bool, ze booljako alias).
Jerry Coffin
1
To nie jest do końca prawda. Na przykład C99 ma long longtyp danych, który nie jest (jeszcze) częścią ISO C ++.
Chinmay Kanchi,
11
Err ... C ++ jest nie tylko zorientowany obiektowo: w C ++ można używać paradygmatów obiektowych, ponieważ język zapewnia takie funkcje, ale także funkcje dla innych paradygmatów. Powinieneś wspomnieć, że to naprawdę ważne, wszystko zmienia. Gdyby tak nie było, wszyscy zmienilibyśmy się na java ...
Klaim
4
Istnieje wiele konstrukcji w C, które nie działają w C ++.
1
@klez: tak - ale nadal jest źle. Podczas gdy ANSI pierwotnie opracował C89 (który nie miał typu logicznego), nowy rozwój jest teraz wykonywany przez ISO, a ANSI akceptuje standard ISO, więc obecny standard ANSI C jest identyczny z obecnym standardem ISO C (który ma typ boolowski).
Jerry Coffin
8

C99 ma kilka funkcji, które nie istnieją (przynajmniej w dokładnie takiej samej formie) w C ++ (np. Elastyczne elementy tablicy, tablice o zmiennej długości itp.)

C99 dodał również wiele do biblioteki, która nie jest obecna w standardzie C ++ 98/03; większość z nich została jednak dodana do C ++ 11.

W zakresie podstawowej orientacji C zasadniczo wspiera ustrukturyzowane programowanie proceduralne. C ++ obsługuje zarówno programowanie obiektowe, programowanie ogólne, jak i metaprogramowanie (przeprowadzanie dowolnych obliczeń w czasie kompilacji). W C ++ 11 dodaje kilka bitów i elementów, które można przynajmniej pomylić z funkcjonalnym wsparciem programowania (np. Wyrażenia lambda). C ++ 14 dodał jeszcze kilka, ale większość z nich jest naprawdę wygodniejsza niż jakakolwiek poważna zmiana orientacji.

Jerry Coffin
źródło
1

Osobiście uważam, że szablony są najważniejszą funkcją, którą C ++ dodaje do C.

zvrba
źródło
1
Eee, a co z klasami z dziedziczeniem? To naprawdę ciężka praca w C, podczas gdy wiele szablonów można wykonać za pomocą makr preprocesora.
JBRWilkinson
4
Makra preprocesorów nie są bezpieczne dla typu; to czysto tekstowe podstawienie, co również utrudnia debugowanie. Aby uzyskać podstawowe klasy i dziedziczenie do pracy, nie jest dużo pracy w C. + możesz stworzyć swój własny model metaobiektu zamiast utknąć w czymkolwiek, co wybrał dla ciebie projektant języka. Patrz, na przykład, ten papier: arxiv.org/abs/1003.2547
zvrba
2
Mój głos będzie destrukcyjny dla najważniejszej funkcji, jaką C ++ ma nad C (nawet nad konstruktorami ze względu na ich niesamowite możliwości czyszczenia).
Thomas Eding
@zvrba #define GENERATE_INTERFACE(T) T T##_func(T x);; (typ) bezpieczne przeciążenie / szablony w C. Zgadzam się z Thomasem, że destruktory są znacznie ważniejszą funkcją, której brakuje C. Ale destruktory często ukrywają ważny kod. Przestrzenie nazw (zakres) są moim zdaniem najważniejsze.
YoYoYonnY