Korzystając z C ++, ale nie używając specyficznych funkcji języka, należy przejść na C?

16

W wolnym czasie opracowuję emulator NES. Używam C ++, ponieważ jest to język, którego najczęściej używam, znam głównie i lubię najbardziej.

Ale teraz, kiedy poczyniłem pewne postępy w projekcie, zdaję sobie sprawę, że nie używam prawie żadnych konkretnych funkcji C ++ i mogłem to zrobić w zwykłym C i uzyskać ten sam rezultat. Nie używam szablonów, przeciążania operatora, polimorfizmu, dziedziczenia. Co byś powiedział? powinienem pozostać w C ++, czy przepisać go w C?

Nie zrobię tego, aby zwiększyć wydajność, może to być efektem ubocznym, ale chodzi o to, dlaczego powinienem używać C ++, jeśli go nie potrzebuję?

Jedyne cechy C ++, których używam, to klasy do enkapsulacji danych i metod, ale można to również zrobić za pomocą struktur i funkcji, używam nowych i usuń, ale równie dobrze mogę używać malloc i za darmo, i jestem używanie dziedziczenia tylko dla wywołań zwrotnych, które można osiągnąć za pomocą wskaźników do funkcji.

Pamiętaj, że to projekt hobbystyczny, nie mam żadnych terminów, więc czas i praca, które wymagałyby ponownego napisania, nie stanowią problemu, mogą być również zabawne. Pytanie brzmi C czy C ++?

Petruza
źródło
3
Wydaje mi się, że sam już odpowiedziałeś: po co używać C ++, jeśli potrzebujesz tylko C? Istnieje wiele sytuacji, w których C jest całkowicie OK.
Giorgio
3
@Giorgio: I wszystkie wyparowują po pierwszych sześćdziesięciu sekundach i musisz zachować swój kod.
DeadMG,
7
I use C++ because is the language I use mostly, know mostly and like mostly.I to jest odpowiedź na twoje pytanie. Powinieneś przełączać języki tylko w połowie projektu, gdy występuje problem, którego twój obecny język nie może rozwiązać. I don't use templates, operator overloading, polymorphism, inheritance.O wiele cenniej byłoby uczyć się i używać pojęć, niż przejść do C. Ponieważ jest to projekt hobby, dlaczego nie skorzystać z kilku rzeczy, których wcześniej nie używałeś? Zawsze możesz rozpocząć inny projekt w języku C i nauczyć się języka, ale w przypadku bieżącego projektu nie ma sensu się przełączać.
yannis
4
Nie używam 100% języka w każdym projekcie, który piszę. Znasz C ++ najlepiej, możesz znaleźć dobre powody, aby korzystać z funkcji, których wcześniej nie znalazłeś. Można zacząć traktować C ++ jako znacznie bezpieczniejsze C, po uruchomieniu za pomocą standardowego rzeczy biblioteki i konstrukty przypominającego podoba std::shared_ptr, std::unique_ptr, boost::scoped_ptr, std::vector, std::deque, std::map, itd. Dla funkcji zwrotnych, spójrz do wykorzystania funktorów, aw C ++ 11, ty może również zacząć korzystać z funkcji takich jak funkcje lambda.
wkl,
3
@Giorgio: Tak. Wywoływanie nieskończonej listy połączonej spowoduje niepotrzebne błędy.
DeadMG

Odpowiedzi:

40

Nie jest używany obecnie, ale następnym razem, gdy wyciek pamięci lub uzyskać podwójne kasowania, będziesz błagać, aby wrócić do std::vector<T>, std::unique_ptr<T, Del>i std::shared_ptr<T>, który może rozwiązać te problemy easily- prawie trywialnie. Tak dzieje się w końcu z każdym, kto używa C w C ++, a mądrzejsi po prostu nie czekają na pojawienie się błędów przed przejściem.

Kod, który używa newi deletebezpośrednio tak naprawdę nie należy do C ++, należy do tego rodzaju domku, który nazywamy „C z klasami”. To miejsce, gdzie język był około roku 1985. To nie jest szczególnie podobny do C ++, około roku 2011. Według wszelkiego prawdopodobieństwa, gdzie nauczyłeś się C ++ po prostu nie uczą go bardzo dobrze, że coś jest niestety dość common- iz lepszą edukację, to będzie znajdź zastosowanie tych funkcji.

W szczególności, jak wymieniłem powyżej, ogólne struktury danych C ++ i klasy zarządzania zasobami po prostu znacznie przewyższają wszystko, co C ma do zaoferowania. Jeśli chcesz dynamicznie alokowanej tablicy, użyj std::vector<T>. To dość powszechny przypadek użycia. Jeśli ich nie używasz, istnieje duże ryzyko niepotrzebnego błędu w kodzie - szczególnie związanego z zarządzaniem zasobami. C ++ może zagwarantować bezpieczeństwo i ponowne użycie kodu w sposób, którego C nigdy nie będzie w stanie dotknąć.

Myślę jednak, że i Ty możesz oczekiwać zbyt wiele. Pisanie szablonów i przeciążanie operatorów nie jest powszechne wśród konsumentów bibliotek. Jeśli używasz kodu std::vector<T>, nie musisz pisać szablonu, aby tak się stało. Jeśli używasz kodu std::string, nikt nie zmusza cię do przeciążenia operatorów. Musisz tylko robić te rzeczy, aby pisać std::vector<T> i std::string- ale nadal możesz z nich w pełni korzystać.

Polimorfizm / dziedziczenie ma również tylko określony przypadek użycia. Jeśli twój kod nie wymaga od ciebie pisania szablonów ani korzystania z funkcji wirtualnych, to tak nie jest, a istnieją programy lub segmenty programów, w których nie musisz pisać własnych szablonów.

Ponadto nie ma wzrostu wydajności w C w porównaniu z C ++.

DeadMG
źródło
1
@Giorgio: make_sharedistnieje i możesz napisać prosty make_uniqueszablon, który wykonuje tę samą pracę. To jest bezpieczniejsze.
DeadMG,
4
Świetna odpowiedź. Gwóźdź na głowie. C ++ jest najbardziej wartościowy dla tych małych bibliotek, których zawsze powinniśmy używać.
Andres Jaan Tack
2
@Giorgio: Jest to niebezpieczne, ponieważ wywołując wiele takich argumentów, możesz dostać przeciek pamięci w przypadku wyjątku i make_sharedjest bardziej wydajny. Tylko funkcje fabryczne mogą gwarantować wyjątkowe bezpieczeństwo.
DeadMG
6
@ tp1: WTF? Proszę po angielsku.
DeadMG,
2
@Lohoris Nie potrzebujesz cytatu dla zdrowego rozsądku. W jaki sposób C powinien być bardziej wydajny niż C ++?
Chris mówi Przywróć Monikę
7

Nawet jeśli nie używasz funkcji specyficznych dla C ++, kompilator C ++ będzie wychwytywał więcej problemów niż C ze względu na bardziej rygorystyczny system C ++.

Nemanja Trifunovic
źródło
6

Spojrzałbym na to z drugiej strony. Czy coś zyskasz przepisując kod w C? Nawet w przypadku projektu czysto hobbystycznego koszty takiego przepisywania są powiązane. Jeśli nic innego, jak przypuszczam, nie byłoby tak zwane kosztem alternatywnym - tj. Innymi rzeczami, które mogłeś zrobić w tym czasie, gdybyś nie marnował czasu na przepisywanie go w C.

Konkluzja: jeśli nie sądzisz, że kod prawdopodobnie zostanie użyty w środowisku, w którym dostęp do C ++ jest naprawdę ograniczony (lub nie istnieje), byłoby to w najlepszym wypadku bezcelowe marnowanie czasu. Przynajmniej z mojego doświadczenia wynika, że ​​zwykle znacznie wykracza poza to bardzo szybko - myśląc o kodzie, który napisałem w C ++, który musiałem przekonwertować na C, całkiem dobrze pamiętam, że nawet w kilku przypadkach wydawało się, że powinno być trywialne, używałem o wiele więcej funkcji specyficznych dla C ++, niż początkowo sobie wyobrażałem. Aby mieć dużą nadzieję, że w ogóle się przydadzą, musiałbyś raczej celować w C89 / 90, w którym to przypadku szybko przypominasz sobie takie rzeczy, jak konieczność zdefiniowania wszystkich zmiennych na początku bloku zamiast tego, gdzie faktycznie są używany.

Krótko mówiąc, chyba że jesteś pewien, że przepisanie w C przyniesie realne korzyści, prawie nieuchronnie jest o wiele lepsze rzeczy do zrobienia.

Jerry Coffin
źródło
+1 Jakiś czas temu musiałem napisać bibliotekę do wykorzystania w innym projekcie C i pomyślałem, że dobrym pomysłem byłoby również zaimplementowanie jej w C, człowieku, co za głupi idiota wtedy byłem.
Chris mówi Przywróć Monikę
1

Jako ogólniejsza odpowiedź:

Nie przełączaj się na C ++ tylko dlatego, że używasz niektórych z jego bardziej unikalnych funkcji. Pewnego dnia możesz potrzebować tych funkcji i po prostu uderzysz się w głowę, ponieważ używasz C.

Dynamiczny
źródło
1

W przypadku rozwoju hobbystów rozważałbym powrót do zwykłych języków C. C i języki podobne do C są częściej obsługiwane w małych modułach do programowania hobby.

Wiele odpowiedzi tutaj może pochodzić z profesjonalnych typów oprogramowania. Jako hobbysta nie będziesz kodować w sposób ciągły ani pełny. Zastanów się więc, w którym języku prawdopodobnie zapamiętasz lub zapomnisz o dziwactwach, jeśli odłożysz projekt na rok, a potem wrócisz i spróbujesz przeczytać kod po tym, jak zaczniesz pisać. C ++, mając bogatszy zestaw funkcji, może wymagać więcej lub mniej czasu, aby ponownie uzyskać, w zależności od stylu kodowania.

hotpaw2
źródło
1

Odpowiedź na pytania nie jest łatwa, ponieważ nie wiemy, czy pracujesz nad projektem, aby poprawić swoje umiejętności językowe (C vs C ++) lub poprawić inne umiejętności programowania (projektowanie, rozwiązywanie problemów itp.).

„Jedyne cechy C ++, których używam, to klasy do enkapsulacji danych i metod, ale można to również zrobić za pomocą struktur i funkcji”. To nie jest prawda. structsw C nie obsługują enkapsulacji i nie mogą zawierać funkcji (metod) - przynajmniej nie bez użycia technik takich jak wskaźniki do funkcji. Ponadto funkcje w C są słabsze, ponieważ nie mogą być przeciążone.

„Używam new i delete, ale równie dobrze mogę używać malloc i free, i używam dziedziczenia tylko do wywołań zwrotnych, które można uzyskać za pomocą wskaźników do funkcji.” Jak deadmg wspomniano, używając bezpośrednio newi deletew C ++ nie jest wskazany. Ponadto dziedziczenie IMHO (i GoF) w OOP powinno być preferowane nad kompozycją tylko wtedy, gdy wymagany jest polimorfizm. I nie sądzę, aby osiąganie polimorfizmu (późne wiązanie) w C przy użyciu wskaźników do funkcji było banalne.

Poza tym nie będę cię przekonywał, że C ++ jest „lepszy” niż C, ponieważ jest to kwestia preferencji i zawsze zależy od problemu, który próbujesz rozwiązać (użycie funkcji OOP do opracowania emulatora NES może być dobry pomysł).

sakisk
źródło
1
structsw C można w rzeczywistości wykorzystać do enkapsulacji metod. Po prostu tworzysz strukturę wskaźników funkcji i inicjujesz je, aby wskazywały dowolne funkcje. Na przykład spójrz na lxr.linux.no/linux+v3.3/include/linux/fs.h#L1598 .
Robert Martin
Zgadza się. Dzięki za komentarz, rozszerzyłem odpowiedź.
sakisk
Ładny. Jeszcze jedna nit: funkcje w C mogą być przeciążone (pomyśl printf), ale robiąc to, tracisz sprawdzanie dowolnego typu. Nie ma sposobu, aby mieć skończony zestaw akceptowalnych deklaracji: jest to 1 (i dostajesz sprawdzanie typu) lub „wiele” (i tracisz wszystkie sprawdzanie typu, na wielkie ryzyko osobiste). Jak w większości rzeczy w C, jest to możliwe, ale często niewygodne.
Robert Martin
Wskaźniki do funkcji są zaawansowaną techniką C? Naprawdę?
Donal Fellows
@DonalFellows Masz rację, przesadziłem. Usunięto zaawansowane ... :)
sakisk,
0

Jestem bardzo początkujący, więc oto moje 2 bity.

Uczę się C i C ++ na Wibit.net z kilkoma ładnymi podstawowymi samouczkami wideo, być może mogą ci bardzo pomóc w omówieniu „sytuacji” (nie reklamy!)

Radzę zmienić się na C, aby się uczyć, ponieważ jesteś hobbystą, będzie to przyjemność, a nie problem.

Radzę więcej. Zrób to w obu językach. Porównaj sposób i rozwiązania, które znajdziesz i wykorzystasz. Jestem pewien, że nie będzie tak łatwo, jak się spodziewasz ... ale na pewno wiele się nauczysz!

H_7
źródło
1
Dziękuję bardzo, ale nie uczę się, już znam C i C ++, pytam, którego użyć do tego konkretnego projektu.
Petruza,
Ups, mój czas na naukę! = P
H_7.
1
Radziłbym również, aby zamiast samouczków wideo, dostać książki Kernigan i Stroustrup, ładne IDE (Visual Studio, Eclipse, Xcode) i uczyć się, kodując przykłady, próby i błędy i uciekając się do stackoverflow.
Petruza
-1

Oto zalety i wady C ++ vs. C:

  1. Przejście do C ułatwiłoby pozostawanie w wybranym podzbiorze C ++, ponieważ kompilator dawałby wtedy błąd, gdy wyjdzie poza niego. Jeśli głównym problemem jest pozostawanie w obrębie określonego podzbioru, należy wybrać tę alternatywę. (dlaczego nie mamy obsługi tego kompilatora?)
  2. Gdy będziesz mógł pozostać w wybranym podzbiorze funkcji c ++, następną rzeczą jest próba zmiany tego podzbioru, aby pozbyć się złych konwencji, które łamią kod. Wymaga to użycia całego c ++.
  3. Kiedy już zarówno „pozostaniesz w podzbiorze”, jak i „to dobry podzbiór”, wyjdź poza funkcje c ++ i zacznij myśleć o wymaganiach.
tp1
źródło