2010-09-01 3 views
7

Zanim cokolwiek, pozwól mi najpierw wyjaśnić, że poniższe myśli są wyłącznie moje osobiste opinie i ze względu na moją ograniczoną wiedzę. Nie mam zamiaru w ogóle mówić, że C++ nie jest cool.C++ z widoku Java: musiałem opuścić kilka rzeczy.

Programowałem C++ przez około rok i myślę, że naprawdę ma kilka fajnych funkcji. Niemniej jednak czuję się trochę pusty i rozczarowany, ponieważ nie nauczyłem się żadnych "zmieniających umysł" rzeczy z C++, z punktu widzenia osoby, która wcześniej nauczyła się Javy (jako pierwszego języka).

Według wielu postów, które przeczytałem, ludzie wolą C++, ponieważ jest to szybsze. Do programisty takiego jak ja, który nie zaprogramował wcześniej aplikacji krytycznych czasowo, jeszcze nie miałem okazji to docenić.

Do tej pory wszystko, czego się dowiedziałem, dotyczyło składni. Tak tworzymy klasę w Javie, a oto jak ją napisać w C++. Oto jak zrobić dziedziczenie w Javie i jak to zrobić w C++ i tak dalej. (Wiem, że wiele dziedziczenia jest fajne, ale dla mnie nie jest rzeczą zmieniającą umysł.) Myślę, że to, co jest fajne, to być w stanie odpowiedzieć, dlaczego Java nie wspierała dziedziczenia wielokrotnego, co ma być bardziej ogólne niż pojedyncze dziedziczenie).

Jak dla mnie, wszystkie są po prostu składnią, a mój umysł nie rozwijał się jak dotąd po napisaniu C++. Myślę, że mój problem polega na pisaniu programów w C++ z "umysłem Java". To, czego naprawdę chcę, to, jak sugeruje wiele osób, zmiana sposobu myślenia po nauczeniu się nowego języka. Do tego jeszcze nie doszło w moim C++.

Potrafię również napisać kilka małych programów w języku Python. Jednak obawiam się dowiedzieć więcej o tym mnie, znowu, to byłby po prostu nauka nowej składni, nowy sposób robienia rzeczy, które są po prostu różne, bez znajomości przyczyn.

Planuję nauczyć się C, aby naprawdę poznać rzeczy. Myślę, że byłby to język "wciągający".

Daj mi znać, co myślisz i daj mi radę.

PS: Btw, jest jedno konkretne pytanie w C++ Chcę potwierdzić. W C++, pisząc w ten sposób, nie jest skuteczny, jeśli się nie mylę:

private A computeAndReturnA(){...} 

Zamiast pisać jako:

private void computeAndReturnA(A& a){...} 

jak w pierwszej sposób zwracane wartości są kopiowane (kiedy przypisujemy b = compute ...) i wprowadzimy pewne nieefektywności? (W Javie, myślę, że pierwsza droga jest jasna w znaczeniu i dobra w wydajności, gdy przechodzi rzeczy przez odniesienie)

+2

C++ i Java są językami zorientowanymi na obiekt, z dużym naciskiem na OOP. W tym sensie są zbyt podobne, aby naprawdę "zmieniały umysł", aby uczyć się jednego po drugim. Zarówno C++, jak i Java mają swoje mocne i słabe strony. Aby mieć naprawdę "zmieniające umysł" doświadczenie, naucz się zupełnie innego rodzaju języka. Python (a także Ruby) jest również dobry, ale możesz wypróbować język funkcyjny podobny do schematu lub haskell lub nawet wypróbować język taki jak prolog, aby uzyskać naprawdę odmienny pogląd na programowanie. Ale na razie pójdę z Pythonem. – MAK

+2

@MAK: Wyraźnie nie zrobiliście wystarczająco dużo C++. C++ jest językiem o wielu paradygmatach. To prawda, że ​​wiele standardowych bibliotek C++ jest oferowanych w formacie OO, ale jest ich wiele. – Puppy

+0

@MAK: Będę musiał zgodzić się z DeadMG tutaj. Przesunięcie paradygmatu z Java na C++ jest ogromne. Jedynym podobieństwem między językami jest składnia (i to było celowe). Sposób, w jaki rzeczy są zrobione poprawnie, jest tak odmienny, że trudno jest programistom Javy (ponieważ mają tendencję do pisania kodu Java w C++). –

Odpowiedz

6

Całkowicie się mylę, krótko mówiąc. Faktem jest, że C++ oferuje OGROMNĄ ilość swobody w porównaniu do Javy.

Na przykład można przydzielić klasy na stosie. Java tego nie oferuje. Możesz obliczyć pewne wartości podczas kompilacji. Szablony oferują znacznie więcej mocy niż generyczne. Masz moc, by uczynić coś odniesieniem lub wartością. W Javie wszystkie te opcje są ci odebrane. Podobnie jak w C++ możesz rozszerzyć więcej niż jedną klasę. Nie jesteś zmuszony do rozszerzenia Obiektu. Deterministyczne zasoby oczyścić, jeśli chcesz. Mógłbym ciągnąć się bez końca.

Jeśli wszystko, co musisz zrobić, to nauczyć się wariantów syntaktycznych, to jest możliwe używanie C++ w nieco akceptowalny sposób. Jednak C++ oferuje dziesiątki rzeczy, których nigdy nie widziałbyś w Javie.

Prosta prawda jest taka, że ​​Java jest bardziej podobna do podgrupy C++ z większą standardową biblioteką, a także, jak sądzę, odbiciem i generowaniem kodu wykonawczego.

Preferuję C++, ponieważ Java, szczerze mówiąc, jest pełna arbitralnych ograniczeń. Czy wiesz, dlaczego nie ma "zaprzyjaźnionego" oświadczenia w Javie? Ponieważ James Gosling uważał, że to było sprzeczne z jego zasadami. Wspaniały. To cudownie. Teraz muszę podzielić moją implementację na dwie klasy i muszę udawać, że to dwie implementacje z oddzielnym hermetyzowaniem, ponieważ myślał dziesięć lat temu, że nie było to właściwe. To jest mój osobisty przykład tego, dlaczego Java jest ogromnie sroga - programujesz jak James Gosling mówi, że powinieneś, a nie jak chcesz lub, w wielu przypadkach, jak naprawdę powinieneś.

Sprawdziłem również Twoje PS. Właśnie dlatego C++ ma odpowiedni kompilator. Rzeczywistość jest taka, że ​​praktycznie wszystkie kompilatory zamieniają pierwszą formę na drugą, a inne optymalizacje, które nie chcą o tym wiedzieć, są wykonywane za kulisami.

+2

OK, możesz robić więcej "fajnych" rzeczy przy pomocy C++, ale czy to pomaga rozwiązywać rzeczywiste problemy, czy może wprowadza kolejny poziom złożoności? – Mot

+1

To nie jest pytanie w PO. Chce wiedzieć, co jest w C++, czego nie ma w Javie, i powiedziałem mu. Poza tym, w jaki sposób posiadanie dokładnie tych samych zdolności co Java, ale więcej NIE pomaga? – Puppy

+0

@mklhmnn, C++ rozwiązuje problemy z prawdziwego świata .. Również nauka może być * złożona * ale nie sądzę, że sam język wprowadza inny poziom złożoności .. – liaK

2

Nauka C to najlepsza opcja tutaj - To doprowadzi cię do gołych kości, które zmusza do nie wykorzystaj swój sposób myślenia w Javie i dzięki temu możesz mieć miłe, łatwiejsze przejście do C++.

+1

Osobiście i inni mogą się nie zgodzić. Czy nauka C jest stratą czasu (jeśli chodzi o pomoc w nauce C++/Jest to złożony język sam w sobie z własnym sposobem robienia rzeczy). Ale to nie ułatwi przejścia na C++. –

+1

C i C++ są zasadniczo podobne. Tak, C++ jest własnym językiem, ale wiedza, w jaki sposób wskaźniki i taka praca są wielką zaletą. – alternative

+0

Współczesne C++ to zupełnie inna bestia od C. Współczesne podejście do C++ podkreśla użycie szablonów, RAII i innych rzeczy, które nie są obecne w większości innych języków programowania, a zdecydowanie nie w C. Tylko dlatego, że oba wskaźniki pomocy C i C++ mają wspólne tło nie czyni ich zasadniczo podobnymi. W rzeczywistości powiedziałbym, że tam, gdzie początkiem projektowania C++ zawsze było rozwiązywanie ogólnych problemów, standard C wydaje się coraz bardziej wspierać specyficzne rzeczy, np. typ "złożony". –

1

Jeśli próbujesz nauczyć się nowych języków, aby poprawić swoje umiejętności programowania, być może spróbuj nauczyć się czegoś, co różni się od składni w stylu C. Być może jeden z języków funkcjonalnych, takich jak Haskell, Scala lub Erlang. Dzięki temu dowiesz się, jak mogą wyglądać różne języki programowania, a także zaczniesz dostrzegać subtelne różnice między Java/C++/C.

W przeciwnym razie, jeśli dążysz do rozwiązania konkretnego problemu, możesz wybrać odpowiedni język. Jeśli nie masz czegoś, co jest krytyczne pod względem wydajności, prawdopodobnie łatwiej jest trzymać się języków, które zbierają śmieci. Jeśli nie planujesz rozwoju iPhone'a, w takim przypadku powinieneś przełączyć się na Objective-C

+0

Dzięki leonm za fajne porady. –

1

Na twoje pytanie: Nadchodzące C++ 0x będzie miało semantykę ruchu, co powinno przyspieszyć "powrót o wartość" do porównywalnych wydajność "powrotu przez odniesienie". Nie wymagają zmiany kodu klienta, ale konieczne może być implementowanie dodatkowego konstruktora w przenoszonych klasach.

O twoim Rantu: Przeczytaj "Współczesny projekt w C++: Ogólne wzorce i wzorce projektowe zastosowane" autorstwa Andrei Alexandrescu i zaskoczony, jak wiele C++ i Java (i odpowiedni sposób myślenia) mogą się różnić.

1

Powodem, dla którego prawdopodobnie nie masz poczucia, że ​​C++ oferuje ci jakikolwiek cukierek dla twojego umysłu jest to, że pochodzisz z tła Java, które do wszystkich intencji i celów oferuje bardzo bezpośrednie i proste tłumaczenie na C++. Nie jest to najlepsze C++, ale możliwe, że działająca implementacja C++ ...

... Powód innego idiomu w przykładzie PS nie ma nic wspólnego z referencjami (których Java nie posiada: Java ma pointers-to-objects, ale nie odwołania, ale C++ ma referencje, a także wskaźniki) i wszystko, co należy zrobić z tym, że w alokacji pamięci Java jest stosunkowo tanie, podczas gdy w C++ nie jest (ponieważ w Javie koszt alokacji pamięci jest amortyzuje wszystko to, co VM musi alokować - i tak w C++ nie jest - więc w Javie VM zapewnia, że ​​pamięć jest alokowana tylko w razie potrzeby).

Tak więc w wydajnym C++ widzisz, że ludzie unikają wielu zbędnych nowych połączeń w ciasnej pętli, podczas gdy w Javie ludzie mogą wygodnie tworzyć tymczasowe obiekty, których tylko chcą.

+0

Czy możesz opracować więcej lub podać kilka wskazówek, dlaczego alokacja pamięci Java jest tania, gdy jest ona oparta na sterty? Moje pytanie brzmi, dlaczego C++ nie może zaimplementować przydzielania pamięci opartej na sterty, tak wydajnej jak Java. Dzięki! –

+0

Ponieważ w C/C++ nowe lub wywołanie malloc jest drogie, podczas gdy w Javie nowe wywołanie stanowi niewiele więcej niż "rezerwowanie" odrobiny wcześniej przydzielonej pamięci przez JVM. Podobnie zwalnianie pamięci nie wymaga przechodzenia przez kosztowne wywołania systemu operacyjnego. lub innymi słowy koszt połączenia malloc/new w podstawowej maszynie JVM jest amortyzowany po * wszystkich * nowych połączeniach w kodzie Java, więc średni koszt pojedynczego nowego wywołania w kodzie Java jest niewielki w porównaniu z C++ . – user268396

+0

@ hungh3, w C++ możesz również wstępnie alokować pule obiektów takich jak Java, a także je rozdzielić i umieścić w puli (również przezroczyste - C++ jest ładne), a tym samym unikać przechodzenia do systemu operacyjnego za każdym razem. - Za cenę małego kodu. – JDonner

2

Prosta prawda jest taka, że ​​nauczenie się myślenia w języku wymaga trochę czasu. najlepsze praktyki.Jest to długi proces, w którym zaczynasz od nauki składni i prawdopodobnie na początku stosuje się najpierw paradygmaty innego języka, aby znaleźć właściwą drogę.

To prawda, że ​​jeśli wybrałbyś język bardzo różny od języka Java - zarówno pod względem składni, jak i paradygmatu - możesz zauważyć te różnice wcześniej, ale nie lekceważ C++ jako innego paradygmatu.

C++ jest językiem, który jest bardzo skomplikowany w nauce, ale jest to język, który może sprawiać wrażenie, że jest łatwy do nauczenia się, szczególnie, że składnia jest podobna do kilku innych języków, jednak jest w tym coś więcej. Jednym z głównych tematów jest na przykład programowanie szablonów, użycie szablonu jest dość proste, jednak jeśli spojrzysz na bibliotekę szablonów boost, to możesz być dość skomplikowany i budowanie takiej biblioteki nie jest dla osób o słabych nerwach.

Nauka języka nie polega jedynie na uczeniu się składni, jej nauce myślenia w tym języku.

To powiedziawszy, C++ jest jednym z języków, który pozwala na tyle wolności i kontroli, ile chcesz, czasem za dużo wolności.

+0

+1 Lubię twój, może być cos * Uczenie się języka to nie tylko uczenie się składni, jej uczenie się myślenia w tym języku * .. :) – liaK

+1

+1 za "czasami za dużo wolności". Myślę, że tak samo jak w życiu (więcej) wolność zwykle wiąże się z (wyższą) ceną, na przykład mniejszym bezpieczeństwem. Kodowanie "normalnych" programów może nie * faktycznie * wymaga dużej swobody ... ale świetne narzędzia i programy tworzone przez prawdziwych hakerów. –

2

Zdecydowanie warto zajrzeć na stronę www.boost.org, która zmieni sposób myślenia.

Jeśli chodzi o pytanie w Post Scriptum: jeśli pierwsza forma będzie dotyczyć kopii lub nie: zależy to od wielu czynników.

W bieżącym C++:

Pierwszym jest to, że jeśli kompilator obsługuje RVO a zwłaszcza, gdy obsługuje również NRVO, szanse są wysokie, kopia nie odbędzie. Wtedy to zależy od tego, jak funkcja jest napisane:

A computeAndReturnA() 
{ 
    return A(x, y); // no copy almost for sure 
} 

A computeAndReturnA() 
{ 
    A a; 
    a.f(); 
    a.g(); 
    return a; // no copy if compiler implements NRVO 
} 

A computeAndReturnA() 
{ 
    A a; 
    while (condition1) { 
     a.f(); 
     if (condition2) 
     return A(); // copy will take place 
    } 
    a.g(); 
    return a; // copy will take place 
} 

potem to zależy od sposobu wywołania funkcji:

A a1 = computeAndReturnA(); // no copy if function body written appropriately, 
           // return value will be constructed directly in a1 
A a2; 
a2.foo(); 
a2 = computeAndReturnA();  // copy regardless of function body, 
           // return value can't directly be constructed in a2 
           // as a2 is already constructed 

W nadchodzącym C++ (marzec 2011):

To samo rozumowanie tak jak w przypadku obecnego C++. Jeśli jednak to rozumowanie sugeruje, że kopia byłaby wykonana, i jeśli klasa (A tutaj) przeniesie konstruktora i przeniesie operator przypisania, to nastąpi "przesuń", a nie "kopiuj". W idealnych przypadkach ruch zostanie odwołany, a także otrzymasz bezpośrednią konstrukcję, ale jeśli nie, otrzymasz ruch w najgorszym przypadku, oczywiście pod warunkiem, że zwrócona klasa jest ruchliwa.

myślę znajdziesz ten artykuł ciekawy i pouczający: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

+0

Dziękuję za wyjaśnienia. Naprawdę wiele się uczę od twojego i od linku. Btw, czy wiesz, jak mogę sprawdzić, czy kompilator wykonuje RVO lub NRVO, czy nie? –

+1

Większość * nowoczesnych * kompilatorów wykonuje oba, jeśli nie wszystkie. GCC dokonuje tego począwszy od wersji 3.1 (około 2002). Ale na pewno uważam, że jedynym sposobem sprawdzenia jest sprawdzenie demontażu wygenerowanego kodu i sprawdzenie, czy wywoływana funkcja przyjmuje ukryty wskaźnik (adres) do skonstruowania wartości zwracanej. Lub kompilator może wskazać, czy obsługuje on RVO w swojej dokumentacji. Na przykład: http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx – usta

+0

Usta, dzięki za porady. –

2

C++ jest znacznie bardziej ogólne niż Java, w tym sensie, że jest, jak wskazano w innych odpowiedzi, język multi-paradygmat, gdzie ponieważ Java tylko podkreśla programowanie zorientowane obiektowo (i jedyny sposób na zrobienie OOP).

Z pewnością można zrobić wiele rzeczy w C++, o których nie można marzyć w Javie. Jednakże, dla kogoś, kto ma doświadczenie w Javie, argumentowałbym, że C++ jest bardzo złym narzędziem do nauki, ponieważ zbyt łatwo jest po prostu kodować w Javie za pomocą kilku "usuniętych" instrukcji tu i tam.

Jeśli chcesz trochę zmienić zdanie, powinieneś nauczyć się języka, który aktywnie podkreśla inny paradygmat, zamiast języka, który pozwala wybrać dowolny paradygmat, który chcesz.

Proponuję jeden z Haskell (programowanie funkcjonalne), Erlang (nietypowe podejście do współbieżności), Factor (programowanie w stosach), Prolog (programowanie logiczne), Common Lisp (CLOS & makra), JavaScript (prototyp- oparty OOP, tzn. bez klas).

Będą to, moim zdaniem, zmieniające umysł doświadczenia edukacyjne. Twierdzę, że pomimo tego, że obsługują wiele rzeczy, których nie ma Java, Python i Ruby wciąż są bardzo zbliżone do modelu Java; w rzeczywistości, z tłem Java, byłoby całkiem łatwo postrzegać je jako kolejną skórkę w tym samym modelu, z nieco odmienną składnią i bez deklaracji typu.

Chodzi mi o to, że jeśli chcesz zdmuchnąć swój umysł, musisz nauczyć się nowego paradygmatu. I choć z pewnością możliwe jest nauczenie się nowych paradygmatów w wystarczająco skutecznym języku, takim jak C++, o wiele łatwiej będzie nauczyć się nowego paradygmatu poprzez naukę języka, który zmusza do użycia tego paradygmatu.

Aby uzyskać krótki przegląd niektórych pomysłów zmieniających świadomość, można obejrzeć these video lectures.

+0

Dzięki za odpowiedź. Twoja odpowiedź ma wiele sensu. A także dzięki za link. Btw, Wydaje mi się, że wszystkie te cenne zasoby rozproszone w sieci, nie wiem, czy wiesz, że ktoś próbował zgromadzić i kategoryzować te zasoby (np. Google Directory)? –