Czym różni się Objective-C od C ++? [Zamknięte]

171

Jakie są główne różnice między Objective-C i C ++ pod względem składni, funkcji, paradygmatów, frameworków i bibliotek?

* Ważne: moim celem nie jest rozpoczęcie wojny wydajnościowej między tymi dwoma językami. Chcę tylko prawdziwych faktów. W rzeczywistości moje pytanie nie jest związane z wydajnością! Proszę podać źródła wszystkiego, co może wydawać się subiektywne.

Alerty
źródło
2
Ten przewodnik zawiera najlepsze porównanie, jakie widziałem.
LiraNuna
@Oskar Kjellin: Odpowiedzi Maca i LiraNuny to doskonałe odpowiedzi. Nie mogę obiektywnie zdecydować, który z nich jest najlepszy, ponieważ oba uzupełniają się nawzajem.
Alerty
@Alerty dobrze wiem (sam się na to często natknę). Może po prostu zaznacz pierwszą odpowiedź jako odpowiedź, co robię, gdy nie mogę się zdecydować. Nie podoba mi się, gdy są pytania, na które nie ma odpowiedzi, gdy są :(
Oskar Kjellin
1
Umieść link do drugiej odpowiedzi w pierwszej i vice / versa
Lee Taylor

Odpowiedzi:

185

Krótka lista niektórych głównych różnic:

  • C ++ umożliwia wielokrotne dziedziczenie, a Objective-C nie.
  • W przeciwieństwie do C ++, Objective-C pozwala na nazwanie parametrów metod, a sygnatura metody zawiera tylko nazwy i typy parametrów oraz typ zwracany (zobacz komentarze bbum i Chucka poniżej). Dla porównania, sygnatura funkcji składowej C ++ zawiera nazwę funkcji, a także tylko typy parametrów / return (bez ich nazw).
  • C ++ zastosowania bool, truei false, używa Objective-C BOOL, YESi NO.
  • C ++ używa void*i nullptr, Objective-C preferuje idi nil.
  • Cel-C używa „selektorów” (które mają typ SEL) jako przybliżonego odpowiednika wskaźników funkcji.
  • Objective-C używa paradygmatu przesyłania wiadomości (a la Smalltalk), w którym można wysyłać „wiadomości” do obiektów za pomocą metod / selektorów.
  • Objective-C z radością pozwoli ci wysłać wiadomość nil, w przeciwieństwie do C ++, który ulegnie awarii, jeśli spróbujesz wywołać funkcję składowąnullptr
  • Objective-C pozwala na dynamiczne wysyłanie, pozwalając klasie odpowiadającej na wiadomość, która jest określana w czasie wykonywania, w przeciwieństwie do C ++, w którym obiekt, dla którego wywoływana jest metoda, musi być znany w czasie kompilacji (patrz komentarz wilhelmtell poniżej). Jest to związane z poprzednim punktem.
  • Objective-C pozwala na automatyczne generowanie akcesorów dla zmiennych składowych przy użyciu „właściwości”.
  • Objective-C umożliwia przypisywanie selfi umożliwia inicjatorom klas (podobnie jak konstruktory) zwracanie w razie potrzeby zupełnie innej klasy. W przeciwieństwie do C ++, gdzie jeśli tworzysz nowe wystąpienie klasy (niejawnie na stosie lub jawnie za pośrednictwem new), gwarantuje się, że będzie to typ, który pierwotnie określiłeś.
  • Podobnie w Objective-C inne klasy mogą również dynamicznie zmieniać klasę docelową w czasie wykonywania, aby przechwytywać wywołania metod.
  • Objective-C nie ma funkcji przestrzeni nazw C ++.
  • Objective-C nie ma odpowiednika referencji C ++.
  • Objective-C nie ma szablonów, preferując (na przykład), aby zamiast tego umożliwić słabe pisanie w kontenerach.
  • Objective-C nie zezwala na niejawne przeciążanie metod, ale C ++ tak. Oznacza to, że w C ++ int foo (void)i int foo (int)zdefiniuj niejawne przeciążenie metody foo, ale osiągnięcie tego samego w Objective-C wymaga jawnych przeciążeń - (int) fooi - (int) foo:(int) intParam. Wynika to z faktu, że nazwane parametry Objective-C są funkcjonalnie równoważne z zniekształceniem nazw w C ++.
  • Objective-C szczęśliwie pozwoli, aby metoda i zmienna miały tę samą nazwę, w przeciwieństwie do C ++, które zazwyczaj mają dopasowania. Wyobrażam sobie, że ma to coś wspólnego z Objective-C używającym selektorów zamiast wskaźników funkcji, a zatem nazwy metod nie mają w rzeczywistości „wartości”.
  • Objective-C nie pozwala na tworzenie obiektów na stosie - wszystkie obiekty muszą być przydzielane ze sterty (jawnie za pomocą allockomunikatu lub niejawnie w odpowiedniej metodzie fabrycznej).
  • Podobnie jak C ++, Objective-C ma zarówno struktury, jak i klasy. Jednak o ile w C ++ są one traktowane prawie tak samo, w Objective-C są traktowane zupełnie inaczej - można na przykład tworzyć struktury na stosie.

Moim zdaniem chyba największą różnicą jest składnia. Możesz osiągnąć zasadniczo to samo w każdym języku, ale moim zdaniem składnia C ++ jest prostsza, podczas gdy niektóre funkcje Objective-C ułatwiają niektóre zadania (takie jak projektowanie GUI) dzięki dynamicznej wysyłce.

Prawdopodobnie wiele innych rzeczy, które przegapiłem, zaktualizuję o inne rzeczy, o których myślę. Poza tym mogę gorąco polecić przewodnik, do którego LiraNuna wskazała. Nawiasem mówiąc, może to być inna interesująca witryna .

Powinienem również zwrócić uwagę, że dopiero zaczynam sam uczyć się Objective-C i jako takie wiele z powyższych może nie być do końca poprawnych lub kompletnych - przepraszam, jeśli tak jest, i witam sugestie ulepszeń.

EDYCJA: zaktualizowano w celu uwzględnienia kwestii podniesionych w poniższych komentarzach, dodano kilka dodatkowych pozycji do listy.

Prochowiec
źródło
8
Przyzwoita lista; jedna korekta. Nie są to „nazwane parametry”, ale „parametry z przeplotem”. Nazwane i „argumenty słów kluczowych” prowadzą do nieporozumień w myśleniu, że można pominąć pewien podzbiór nazwy metody. Nie może.
bbum
7
Zapomniałeś wymienić najważniejszą różnicę: Object-C używa wysyłania dynamicznego, podczas gdy C ++ używa wysyłania statycznego. Innymi słowy, kod skompilowany przez kompilator Objective-C będzie miał klasę odpowiedzialną za odpowiadanie na komunikat określony w czasie wykonywania; kod skompilowany przez kompilator C ++ ma te informacje obliczone i wkompilowane w czasie kompilacji.
wilhelmtell
9
@wilhelmtell: Kompilator C ++ zna tylko nadklasę w czasie kompilacji. W czasie wykonywania rzeczywistą klasą może być dowolna klasa potomna. Jest to również forma dynamicznej wysyłki, ale nie taka sama, jak w przypadku Celu C. Tylko uważaj na te terminy techniczne!
Norman Ramsey
5
+1 Dobra lista. Jednak Objective-C również używa void*i NULL, tylko nie dla obiektów. Możesz użyć dowolnego wskaźnika w stylu C w Obj-C, a wiele wywołań API faktycznie przekazuje lub zwraca wartości przez odwołanie, w którym NULLto przypadku jest często używane.
Quinn Taylor
3
@wilhelmtell - nie wiem nic o Objective-C, ale w C ++ MOŻESZ dynamicznie odpowiadać innej klasie na wywołanie funkcji, ale musiałbyś mieć coś w rodzaju tablicy wskaźników do klasy bazowej, a następnie klas ACTUAL które „wiszą” na nim. Chociaż wszystkie klasy muszą istnieć podklasy, wywołanie metody BĘDZIE wywoływać różne metody w zależności od klasy, w czasie wykonywania.
Kevin Anderson
33

Chociaż oba są zakorzenione w C, są to dwa zupełnie różne języki.

Główną różnicą jest to, że Objective-C koncentruje się na decyzjach uruchomieniowych dotyczących wysyłania i w dużej mierze zależy od biblioteki wykonawczej, która obsługuje dziedziczenie i polimorfizm, podczas gdy w C ++ nacisk kładzie się zwykle na decyzje statyczne, czas kompilacji.

Jeśli chodzi o biblioteki, możesz używać zwykłych bibliotek C w obu językach - ale ich biblioteki natywne są zupełnie inne.

Interesujące jest jednak to, że możesz mieszać oba języki (z pewnymi ograniczeniami). Wynik nazywa się Objective-C ++ .

Georg Fritzsche
źródło
zaktualizowany link: Objective-C ++
IcyIcicle
6

Są zupełnie inni. Cel C ma więcej wspólnego z Smalltalk niż z C ++ (no cóż, z wyjątkiem składni, naprawdę).

Dean Harding
źródło
6

Z czubka mojej głowy:

  1. Style - Obj-C jest dynamiczny, C ++ jest zazwyczaj statyczny
  2. Chociaż oba są OOP, jestem pewien, że rozwiązania byłyby inne.
  3. Inny model obiektowy (C ++ jest ograniczony przez system typów w czasie kompilacji).

Dla mnie największą różnicą jest system modelowy. Obj-C umożliwia wysyłanie wiadomości i introspekcję, ale C ++ ma zawsze tak potężne szablony.

Każdy ma swoje mocne strony.

Rev316
źródło
5

Jak powiedzieli inni, Objective-C jest znacznie bardziej dynamiczny, jeśli chodzi o to, jak myśli o obiektach w porównaniu z dość statycznym obszarem C ++.

Objective-C, będąc w linii Smalltalk języków zorientowanych obiektowo, ma koncepcję obiektów, która jest bardzo podobna do tej z Javy, Pythona i innych "standardowych" języków obiektowych innych niż C ++. Wiele dynamicznych wysyłek, brak przeciążenia operatorów, wysyłanie wiadomości.

C ++ to własne dziwne zwierzę; przeważnie pomijał część Smalltalk drzewa genealogicznego. W pewnym sensie ma dobry system modułowy z obsługą dziedziczenia, który może być używany do programowania obiektowego. Rzeczy są znacznie bardziej statyczne (na przykład metody nadpisywalne nie są domyślne).

Michael Ekstrand
źródło
4

Objective-C jest doskonalszym nadzbiorem C. W C i Objective-C void*dozwolone jest niejawne rzutowanie ze wskaźnika do struktury.

Foo* bar = malloc(sizeof(Foo));

C ++ nie skompiluje się, chyba że voidwskaźnik zostanie jawnie rzutowany:

Foo* bar = (Foo*)malloc(sizeof(Foo));

Znaczenie tego dla codziennego programowania wynosi zero, po prostu zabawny fakt.

Igor Zevaka
źródło
Drugi przykład nie jest kodem w C ++. To kod w C spowodował błąd, gdy próbowałeś go skompilować za pomocą kompilatora C ++. Jeśli chcesz, aby stary C ++ był jak najbardziej zbliżony do oryginału, napisz, Foo* bar = reinterpret_cast< Foo* >(malloc(sizeof(Foo));a potem może użyj konstruktora inplace. Ale od dzisiaj jego nowoczesny C ++ jest bardziej taki, auto bar = new Foo(constructorArg);że nie potrzebujesz malloc, i albo callic, możesz użyć std::vector::reserve, istd::vector::emplace_mack
xakepp35
3

Obj-C ma znacznie bardziej dynamiczne możliwości w samym języku, podczas gdy C ++ jest bardziej skoncentrowany na możliwościach kompilacji z pewnymi dynamicznymi możliwościami.

W C ++ parametryczny polimorfizm jest sprawdzany w czasie kompilacji, podczas gdy w Obj-C polimorfizm parametryczny jest uzyskiwany poprzez dynamiczne wysyłanie i nie jest sprawdzany w czasie kompilacji.

Obj-C ma bardzo dynamiczny charakter. Możesz dodawać metody do klasy w czasie wykonywania. Posiada również introspekcję w czasie wykonywania, aby przyjrzeć się klasom. W C ++ definicja klasy nie może się zmienić, a cała introspekcja musi zostać przeprowadzona w czasie kompilacji. Chociaż dynamiczną naturę Obj-C można osiągnąć w C ++ za pomocą mapy funkcji (lub czegoś podobnego), jest ona nadal bardziej szczegółowa niż w Obj-C.

W C ++ jest znacznie więcej sprawdzeń, które można wykonać w czasie kompilacji. Na przykład przy użyciu typu wariantowego (takiego jak unia) kompilator może wymusić, że wszystkie przypadki są zapisywane lub obsługiwane. Więc nie zapomnij o rozwiązywaniu skrajnych przypadków problemu. Jednak wszystkie te kontrole mają swoją cenę podczas kompilacji. Obj-C kompiluje się znacznie szybciej niż C ++.

Paul Fultz II
źródło
3
Jeśli masz zamiar rozmawiać o cenach, bądź uczciwy! I odwrotnie, Obj-C jest znacznie wolniejszy w rozwiązywaniu wywołań metod dynamicznych w czasie wykonywania niż C ++. I argumentowałbym, że szybkość kompilacji jest względną trywialnością w porównaniu z szybkością działania. Jestem pewien, że Obj-C oferuje wiele korzyści ze względu na bardziej dynamiczną wysyłkę, ale istnieje kompromis.
underscore_d
1
To prawda, że ​​istnieje kompromis między czasem wykonywania a kosztem czasu kompilacji. Jednak czas kompilacji nie zawsze jest trywialny. Używanie ciężkiego metaprogramowania i bibliotek EDSL w C ++ (takich jak Boost.Spirit) może mieć drastyczny wpływ na czas kompilacji, jednocześnie tworząc bardzo szybki kod w czasie wykonywania.
Paul Fultz II
1
Jasne, zbytnio upraszczałem w stosunku do POV prostszych baz kodów ... Przy bardzo złożonych bazach kodu, ponowna kompilacja w celu przetestowania małych zmian może uczynić programowanie bardzo żmudnym, co nie jest trywialne. Ale czy jest to coś, co naprawdę możemy porównać między nimi? Czy takie biblioteki, tak zależne od funkcji czasu kompilacji C ++, mogą zostać w jakiś sposób zmienione w Objective-C i pokazać, że kompilują się szybciej? tj. czy stwierdzenie „Obj-C jest znacznie szybsze w kompilacji niż C ++” odnosi się do równoważnych baz kodu, dla których można zmierzyć replikowalne przyspieszenie? W przeciwnym razie porównujemy czas uprawy jabłek z pomarańczami.
underscore_d