Dotyczy to nie tylko C ++, ale każdego języka, który udostępnia zarówno struktury, jak i klasy.
Jason Bunting,
3
Nadal się nie zgadzam - podchodzę do tego pytania semantycznie. Być może istnieją pewne różnice techniczne, ale semantycznie nie są. Struktury są naprawdę przydatne do tworzenia typów wartości, klasy nie.
Jason Bunting,
4
Uważam, że nie ma poważnego powodu do używania struktur w C ++. Dla mnie struktury są kolejną nadmiarową „funkcją” C ++, która istnieje tylko dla kompatybilności z C, jak typedefs. Nie istniałyby, gdyby C ++ nie był początkowo traktowany jako rozszerzenie do C i został zaprojektowany od podstaw, taki jak Java. Ogólnie rzecz biorąc, uważam, że wiele najdziwniejszych rzeczy w C ++ ma związek z kompatybilnością z C.
Kostas
5
Struct - dla POD (zwykłe stare dane) i dostępność wszystkich członków jest publiczna. Klasa - gdy potrzebujesz lepszej enkapsulacji i potrzebujesz funkcji członkowskich do pracy ze stanem klasy.
Navaneeth KN
4
Dotyczy to tylko konwencji. Nie ma różnicy, oprócz domyślnej enkapsulacji.
Dave Hillier
Odpowiedzi:
804
Różnice między classai structw C ++ polegają na tym, że struktury mają domyślne publicelementy i bazy, a klasy mają domyślne privateelementy i bazy. Obie klasy i kodowanym może mieć mieszankę public, protectediprivate członkowie mogą korzystać z dziedziczenia i mogą mieć funkcje składowe.
Poleciłbym używanie struktur jako zwykłych struktur danych bez żadnych funkcji podobnych do klas, i używanie klas jako agregujących struktur privatedanych z danymi i funkcjami składowymi.
Strukturę bez modyfikatorów i metod nazywa się strukturą POD, która istnieje jako kompatybilny wstecz interfejs z bibliotekami C, ponieważ (podobno) gwarantuje się, że będzie ułożona tak, jakby była strukturą C. Oprócz tego jednego wyjątku jedyną różnicą jest to, co podano.
workmad3
26
@ workmad3: Nazwa wprowadza w błąd, ale 9/4 (C ++ 03) mówi: „POD-struct jest klasą agregującą, która nie ma elementów niestatycznych typu non-POD-struct, non-POD-union (lub tablica takich typów) lub odwołanie, i nie ma operatora przypisania kopii zdefiniowanego przez użytkownika ani destruktora zdefiniowanego przez użytkownika. ” Nie ma ograniczeń w używaniu klucza klasy „struct” i nie ma ograniczeń w używaniu „public” (wymagania zagregowane podano w 8.5.1 / 1). To nie jest różnica między „struct” a „class”.
5
Twoje użycie „agregatu” może być źle zrozumiane, biorąc pod uwagę definicję standardu. :)
3
Zgodnie z książką Stroustrupa „Zasady i praktyka”: „struktury powinny być używane przede wszystkim tam, gdzie członkowie mogą przyjmować dowolną wartość” (tzn. Tam, gdzie nie można zdefiniować znaczącego niezmiennika klasowego)
antius
6
Oczywiście możesz używać klas, gdy współpracujesz z C. Nie ma różnicy między klasami a strukturami. Struktury są klasami; tylko domyślny dostęp jest przełączany z prywatnego na publiczny.
Sebastian Mach
229
Jak wszyscy zauważają, w rzeczywistości istnieją tylko dwie rzeczywiste różnice językowe:
structdomyślnie dostęp publiczny i classdomyślny dostęp prywatny.
Podczas dziedziczenia structdomyślnie przyjmuje publicdziedziczenie i classdomyślnie privatedziedziczenie. (Jak na ironię, podobnie jak w przypadku wielu rzeczy w C ++, domyślnie jest to wstecz: publicdziedziczenie jest zdecydowanie bardziej powszechnym wyborem, ale ludzie rzadko deklarują, structże oszczędzają na wpisaniu publicsłowa kluczowego „ ”.
Ale prawdziwa różnica w praktyce między class/ struct, który deklaruje konstruktora / destruktora i jeden, który nie. Istnieją pewne gwarancje na POD typu „zwykłe stare dane”, które nie obowiązują już po przejęciu konstrukcji klasy. Aby zachować to rozróżnienie, wiele osób celowo używa tylko structs dla typów POD, a jeśli zamierzają w ogóle dodać jakiekolwiek metody, używają classes. Różnica między dwoma fragmentami poniżej jest bez znaczenia:
class X
{public:// ...};struct X
{// ...};
(Nawiasem mówiąc, oto wątek z kilkoma dobrymi objaśnieniami, co tak naprawdę oznacza „typ POD”: Co to są typy POD w C ++? )
Ładny przykład dotyczący różnic w dziedziczeniu: tutaj .
Liran Orevi
8
Czy używasz structlub classnie ma żadnego wpływu na to, czy obiekt POD czy należy zdefiniować konstruktor kopiuj / destruktora. Funkcje składowe również nie mają wpływu na to, że coś jest POD. Kiedy ponownie czytam to, co napisałeś, widzę, że nie sugerujesz inaczej, ale obecne sformułowanie jest mylące
David Stone
1
@DavidStone Zasadniczo struktury POD mają gwarantować zgodność wsteczną z kodem C, a zatem zasadniczo powinny być zaprojektowane jako struktury typu C.
Justin Time - Przywróć Monikę
3
„Prawdziwa różnica” w tej odpowiedzi jest całkowicie błędna.
juanchopanza
177
Istnieje wiele nieporozumień w istniejących odpowiedziach.
Tak, może być konieczne przestawienie słów kluczowych modyfikujących dostęp w definicji klasy, w zależności od słowa kluczowego użytego do zadeklarowania klasy.
Ale poza składnią jedynym powodem, aby wybierać między innymi, jest konwencja / styl / preferencja.
Niektórzy ludzie lubią trzymać się structsłowa kluczowego dla klas bez funkcji składowych, ponieważ wynikowa definicja „wygląda jak” prosta struktura z C.
Podobnie, niektórzy ludzie lubią używać classsłowa kluczowego dla klas z funkcjami i privatedanymi składowymi, ponieważ na nim jest napisane „klasa”, a zatem wyglądają jak przykłady z ich ulubionych książek na temat programowania obiektowego.
Rzeczywistość jest taka, że to całkowicie zależy od ciebie i twojego zespołu, i to dosłownie nie zrobi żadnej różnicy dla twojego programu.
Poniższe dwie klasy są absolutnie równoważne pod każdym względem oprócz ich nazwy:
structFoo{int x;};classBar{public:int x;};
Możesz nawet przełączać słowa kluczowe podczas ponownego tworzenia:
Pamiętaj jednak, że nie można zmieniać słów kluczowych podczas redefiniowania ; dzieje się tak tylko dlatego, że (zgodnie z regułą jednej definicji) zduplikowane definicje klas w jednostkach tłumaczeniowych muszą „składać się z tej samej sekwencji tokenów” . Oznacza to, że nie możesz nawet wymieniać const int member;się int const member;i nie ma to nic wspólnego z semantyką classlub struct.
To była bardzo pouczająca i szczerze mówiąc moja ulubiona odpowiedź. Wszyscy inni traktują je jako oddzielne byty, pod maską są takie same. Zastanawiam się, czy definicja struktury w środowisku Arduino jest uważana za klasę CPP, ponieważ jest skompilowana przy użyciu g ++.
Benjamin
4
@Ben Oczywiście, że tak. Kompilator Arduino kompiluje C ++; to koniec.
underscore_d
6
Jeśli więc rozumiem to dobrze: dopóki modyfikatory widoczności są wyraźne, a nie pominięte, nie ma to znaczenia. Mógłbyś napisać ogromną aplikację w C ++ używając wyłącznie struktur; lub możesz przejść i zmienić każdy przypadek struktury na klasę. Dopóki nie używasz domyślnej widoczności, aplikacje będą dokładnie takie same.
Ryan Lundy,
Nie jestem przekonany, że jedna jednostka tłumacząca programu C ++ może mieć pełną deklarację, class foo { public: ... };a inna może mieć, struct foo { ... };co musiałoby być zgodne z twierdzeniem „absolutnie równoważnym”. Chodzi o przyczyny, że niepełne oświadczenia struct foo;i class foo;są wymienne. Nie określają one treści klasy, więc nie mówią nic o układzie dostępu.
Kaz
@Kaz: Masz rację - jeśli definicje były dosłownie tego samego typu, muszą być one identyczne leksykalnie, aby zachowanie było dobrze zdefiniowane. Struct-key i klasa-key to inaczej chociaż logicznie wymienny (gdzie semantyka nie dotyczy), a Fooi Barnadal są równoważne / identyczne typy. Upewniłem się, że powiedziałem „przy ponownym zgłaszaniu ” i podałem przykład. Pomyśl o tym, wyjaśnię to w odpowiedzi, aby upewnić się, że nie wprowadzam ludzi w błąd UB
Lekkość ściga się na orbicie
54
Jedynym razem, gdy używam struktury zamiast klasy, jest deklarowanie funktora tuż przed użyciem go w wywołaniu funkcji i chcę zminimalizować składnię ze względu na przejrzystość. na przykład:
Członkowie i podstawowe klasy struktury są domyślnie publiczne, podczas gdy w klasie domyślnie są prywatne. Uwaga: powinieneś jawnie uczynić swoje klasy podstawowe publicznymi, prywatnymi lub chronionymi, zamiast polegać na ustawieniach domyślnych.
struct i klasa są poza tym funkcjonalnie równoważne.
OK, dość tej piszczącej czystej techno. Emocjonalnie większość programistów dokonuje wyraźnego rozróżnienia między klasą a strukturą. Struktura po prostu wydaje się być otwartą stertą bitów z bardzo małą ilością możliwości enkapsulacji lub funkcjonalności. Klasa czuje się jak żywy i odpowiedzialny członek społeczeństwa z inteligentnymi usługami, silną barierą hermetyzacji i dobrze zdefiniowanym interfejsem. Ponieważ taka konotacja ma już większość ludzi, prawdopodobnie powinieneś użyć słowa kluczowego struct, jeśli masz klasę, która ma bardzo mało metod i dane publiczne (takie rzeczy istnieją w dobrze zaprojektowanych systemach!), Ale w przeciwnym razie prawdopodobnie powinieneś użyć tej klasy słowo kluczowe.
Nie rozumiem, dlaczego twierdzą, że struktura i klasa są funkcjonalnie takie same, ale w niektórych przypadkach mówią, że wolą jedną od drugiej, bez żadnego uzasadnienia.
deetz
3
Powodem jest konwencja. Kompilator nie dba o to, którego używasz, ale inny programista patrząc na twój kod będzie miał łatwiejszy czas na zrozumienie, co masz na myśli.
Tal Pressman
3
@deetz: Cały trzeci akapit jest uzasadnieniem.
Wyścigi lekkości na orbicie
Wow, pochodząc ze „starej szkoły” nie miałem pojęcia, że struktura może mieć metody, a nawet dziedziczenie. Zawsze korzystałem z struct, gdy używam tylko danych bez żadnych metod i zwykle dotyczy to kodu API, który potrzebuje struktury. Czy struktury mogą obsługiwać także wielokrotne dziedziczenie?
Paul McCarthy
21
Jednym z miejsc, w którym struktura była dla mnie pomocna, jest system, który odbiera komunikaty o stałym formacie (np. Port szeregowy) z innego systemu. Możesz rzutować strumień bajtów na strukturę, która definiuje twoje pola, a następnie łatwo uzyskać do nich dostęp.
Lub możesz po prostu zaimplementować operator >>na klasie zamiast pisać processMessagefunkcję, dzięki czemu Twój C ++ będzie wyglądał bardziej jak poprawny C ++, a mniej jak C.
Nick Bastin
1
Poza tym, że nie jest przenośny między różnymi systemami, narusza to zasady aliasingu, więc nie gwarantuje się, że będzie działał nawet w ramach jednej architektury.
underscore_d
@underscore_d Może to działać niezależnie od platformy (ale nie kompilatora), ale musisz używać stałych pól bitowych, __packed__struktury i mieć implementację ifdef obsługującą endian (musisz zmienić kolejność na komputerze, na którym endianess jest przeciwny do zewnętrznego źródła danych zapewnia). To nie jest ładne, ale zwykłem pakować / rozpakowywać rejestry zdalnych urządzeń peryferyjnych na platformach wbudowanych w przenośny sposób.
poważny
1
@jacwah Huh, dobry punkt. Aliasing nie będzie tutaj problemem, ponieważ jednym ze wskaźników jest chartyp, który jest zwolniony z aliasingu. Jednak nadal istnieje problem, choć inny: rzutowanie char*na inny typ, jeśli tak naprawdę nie było już żadnego obiektu tego drugiego typu, który został już zainicjowany pod tym adresem, jest UB, ponieważ narusza reguły życia. Afaik, nawet jeśli typ docelowy jest trywialnie konstruowalny, samo przydzielenie pamięci nie jest wystarczające, aby C ++ formalnie pozwalał na traktowanie tej pamięci jako tego typu.
underscore_d
19
Możesz użyć „struct” w C ++, jeśli piszesz bibliotekę, której wewnętrznymi elementami są C ++, ale API można wywoływać za pomocą kodu C lub C ++. Po prostu tworzysz pojedynczy nagłówek, który zawiera struktury i globalne funkcje API, które udostępniasz zarówno kodowi C, jak i C ++ w następujący sposób:
// C access Header to a C++ library#ifdef __cpp
extern"C"{#endif// Put your C struct's herestruct foo
{...};// NOTE: the typedef is used because C does not automatically generate// a typedef with the same name as a struct like C++.typedefstruct foo foo;// Put your C API functions herevoid bar(foo *fun);#ifdef __cpp
}#endif
Następnie możesz napisać pasek funkcji () w pliku C ++ za pomocą kodu C ++ i ustawić go jako wywoływalny z C, a dwa światy mogą dzielić dane poprzez zadeklarowane struktury. Istnieją oczywiście inne zastrzeżenia dotyczące mieszania C i C ++, ale jest to uproszczony przykład.
Najlepsza odpowiedź. Zgodność z C jest naprawdę najważniejszym powodem. wszystkie inne rzeczy, takie jak domyślny dostęp, są ezoteryczne.
Valentin Heinitz
16
Jak wszyscy mówią, jedyną prawdziwą różnicą jest domyślny dostęp. Ale szczególnie używam struct, gdy nie chcę żadnego enkapsulacji za pomocą prostej klasy danych, nawet jeśli zaimplementuję jakieś metody pomocnicze. Na przykład, gdy potrzebuję czegoś takiego:
+1 za podanie przykładu struktury z niektórymi funkcjami składowymi, które nie wydają się „zabrane ze struktury”.
einpoklum
9
Aby odpowiedzieć na moje pytanie (bezwstydnie), jak już wspomniano, uprawnienia dostępu są jedyną różnicą między nimi w C ++.
Zwykle używam struktury tylko do przechowywania danych. Pozwolę mu uzyskać kilka funkcji pomocniczych, jeśli ułatwi to pracę z danymi. Jednak gdy tylko dane wymagają kontroli przepływu (tj. Pobierające / ustawiające, które utrzymują lub chronią stan wewnętrzny) lub zaczynają uzyskiwać jakąkolwiek większą funkcjonalność (zasadniczo bardziej obiektową), zostaną „uaktualnione” do klasy, aby lepiej komunikować zamiary.
Struktury ( POD , bardziej ogólnie) są przydatne, gdy zapewniasz interfejs kompatybilny z C z implementacją C ++, ponieważ są one przenośne ponad granicami języków i formatami linkerów.
Jeśli to nie dotyczy ciebie, to przypuszczam, że użycie „struct” zamiast „class” jest dobrym komunikatorem intencji (jak wspomniano powyżej @ ZeroSignal). Struktury mają również bardziej przewidywalną semantykę kopiowania, więc są przydatne w przypadku danych, które zamierzasz zapisać na nośniku zewnętrznym lub przesłać przewodowo.
Struktury są również przydatne do różnych zadań metaprogramowania, takich jak szablony cech, które po prostu ujawniają kilka zależnych typów typów:
template<typename T>struct type_traits {typedef T type;typedef T::iterator_type iterator_type;...};
... Ale tak naprawdę to korzysta z domyślnego poziomu ochrony structa, który jest publiczny ...
To nie jest prawidłowe użycie POD. Struktura (lub klasa) może być strukturą POD, jeśli (i tylko jeśli) zawiera TYLKO członków POD.
Martin York
4
„przewidywalna semantyka kopiowania”: Symantyka jest taka sama jak dla klasy (i mają te same problemy (płytka kopia)).
Martin York
2
Ten post pozwoliłby ci uwierzyć (mam nadzieję, że przypadkiem), że wszystkie struktury są POD. To wcale nie jest prawda. Mam nadzieję, że ludzie nie są przez to wprowadzani w błąd.
Michael Dorst
8
W przypadku C ++ naprawdę nie ma dużej różnicy między strukturami a klasami. Główną różnicą funkcjonalną jest to, że członkowie struktury są domyślnie publiczni, podczas gdy domyślnie są prywatni w klasach. W przeciwnym razie, jeśli chodzi o język, są one równoważne.
To powiedziawszy, zwykle używam struktur w C ++, tak jak robię to w C #, podobnie jak powiedział Brian. Struktury są prostymi kontenerami danych, podczas gdy klasy są używane dla obiektów, które muszą oddziaływać na dane oprócz tylko ich trzymania.
Są prawie takie same. Dzięki magii C ++, struct może przechowywać funkcje, używać dziedziczenia, tworzone przy użyciu „new” i tak dalej jak klasa
Jedyną różnicą funkcjonalną jest to, że klasa zaczyna się od prywatnych praw dostępu, a struct zaczyna się od public. Jest to zachowanie zgodności wstecznej z C.
W praktyce zawsze używałem struktur jako posiadaczy danych, a klas jako obiektów.
Pamiętaj jednak, że nie jest mądre przekazywanie dalej czegoś. jako class ( class X;) i zdefiniuj go jako struct ( struct X { ... }). Może działać na niektórych linkerach (np. G ++) i może zawieść na innych (np. MSVC), więc znajdziesz się w piekle programisty.
@LightnessRacesinOrbit Niestety nie mogę. Nie jestem nawet w stanie stworzyć przykładu. Trywialna class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }nie tylko kompiluje się i działa z MSVC 2017, ale nawet tworzy wyraźne ostrzeżenie, które Foozostało zadeklarowane jako structzdefiniowane jako class. Ale pamiętam też wyraźnie, że znalezienie tego głupiego robaka kosztowało nasz zespół pół dnia. Nie jestem pewien, jakiej wersji MSVC używaliśmy wtedy.
pasbi
Łącznik nie powinien nawet wiedzieć o tym, czy używane classlub structna przednim deklaracji, a dwa są swobodnie wymienialne na standardzie (choć wiadomo, że VS ostrzega, zawsze zakłada się, że właśnie w celu uniknięcia widocznych błędów programista). Coś tu nie pachnie. Czy na pewno nie był to błąd naruszenia ODR?
Nie pamiętam dokładnie. Problem nie wystąpił bezpośrednio w aplikacji, ale w bibliotece używanej w gtest. Wiem tylko, że linker spowodował niezrozumiałe błędy (LNK ???). Gdy zastąpiłem- structForward na- classForward, problemy zniknęły. Na dzień dzisiejszy też wydaje mi się to dziwne. Byłbym zadowolony, gdybyś mógł rzucić na to trochę światła.
pasbi
3
Klasa.
Członkowie klasy są domyślnie prywatni.
class test_one {int main_one();};
Jest równa
class test_one {private:int main_one();};
Więc jeśli spróbujesz
int two = one.main_one();
Otrzymamy błąd: main_one is privateponieważ nie jest dostępny. Możemy go rozwiązać, inicjując go, określając go jako publiczny, tj
class test_one {public:int main_one();};
Struct.
Struktura to klasa, w której członkowie są domyślnie publiczni.
struct test_one {int main_one;};
Środki main_onesą prywatne tj
class test_one {public:int main_one;};
Używam struktur do struktur danych, w których członkowie mogą przyjmować dowolną wartość, w ten sposób jest łatwiej.
Zaletą structprzez classto, że uratować jedną linię kodu, jeśli przylegającą do „pierwszych członków publicznych, następnie prywatna”. W tym świetle znajduję słowo kluczoweclass bezużyteczne.
Oto kolejny powód używania tylko structi nigdy class. Niektóre wytyczne dotyczące stylu kodu dla C ++ sugerują używanie małych liter w makrach funkcyjnych, uzasadnieniem jest to, że kiedy makro jest konwertowane na funkcję wbudowaną, nazwa nie powinna wymagać zmiany. To samo tutaj. Masz swoją ładną strukturę w stylu C i pewnego dnia dowiadujesz się, że musisz dodać konstruktor lub jakąś wygodną metodę. Czy zmienisz to na class? Wszędzie?
Rozróżnianie structs oraz classes jest po prostu zbyt wiele kłopotów, dostając w zasadzie robi to, co powinniśmy robić - programowanie. Podobnie jak wiele problemów C ++, wynika on z silnego pragnienia wstecznej kompatybilności.
Dlaczego miałbyś zmienić to na class? Czy uważasz, że klasa zdefiniowana za pomocą structsłowa kluczowego nie może mieć funkcji członka ani konstruktora?
Wyścigi lekkości na orbicie
@LightnessRacesinOrbit z powodu 1. spójności i 2. niektórych analizatorów statycznych narzeka na naruszenie 1.
Vorac
To nie następuje. Jakich innych „konsystencji” przestrzegasz? Każda klasa z wywoływanym członkiem joe()musi być zdefiniowana za pomocą classsłowa kluczowego? Każda klasa z co najmniej 4 intczłonkami musi być zdefiniowana za pomocą structsłowa kluczowego?
Wyścigi lekkości na orbicie
@LightnessRacesinOrbit Mam na myśli idiom „Agregaty POD są zdefiniowane za pomocą struct, agregaty metodami są zdefiniowane za pomocą class”. Za dużo kłopotów.
Vorac
2
są takie same z różnymi ustawieniami domyślnymi (domyślnie prywatne classi publiczne dla struct), więc teoretycznie są one całkowicie wymienne.
więc jeśli chcę tylko spakować jakieś informacje, aby się poruszać, używam struktury, nawet jeśli podam tam kilka metod (ale nie wiele). Jeśli jest to w większości nieprzejrzyste, gdzie głównym zastosowaniem byłyby metody, a nie bezpośrednio członkowie danych, używam pełnej klasy.
Struktury domyślnie mają dostęp publiczny, a klasy domyślnie mają dostęp prywatny.
Osobiście używam struktur do przenoszenia danych lub jako obiektów wartości. W takim przypadku deklaruję wszystkich członków jako const, aby zapobiec modyfikacji przez inny kod.
Zarówno structi classsą takie same pod maską choć z różnych domyślnych co do widoczności, structdomyślnie jest publiczny i classdomyślnie jest prywatny. Możesz zmienić jedno z nich, używając odpowiednio privateipublic . Obie pozwalają na dziedziczenie, metody, konstruktory, destruktory i wszystkie inne zalety języka zorientowanego obiektowo.
Jednak jedna ogromna różnica między nimi polega na tym, że structsłowo kluczowe jest obsługiwane w języku C, podczas gdy classnie. Oznacza to, że można używać structw include pliku, który można #includew każdej C ++ lub C tak długo, jak structto zwykły C styl structi wszystko w include plik jest kompatybilny z C, to znaczy nie C ++ konkretne słowa kluczowe, takie jak private, publicnie metody, brak dziedziczenia itp. itd. itd.
Styl AC structmoże być używany z innymi interfejsami, które obsługują styl C structdo przenoszenia danych tam iz powrotem przez interfejs.
Styl AC structto rodzaj szablonu (nie szablon C ++, ale raczej wzór lub szablon), który opisuje układ obszaru pamięci. Z biegiem lat interfejsy użytkowej z C i C wtyczek (tu patrzy na ciebie Java i Python i Visual Basic) zostały stworzone z których niektóre prace z klasą C struct.
Kiedy zdecydujesz się użyć struct, a kiedy klasy w C ++?
Używam, structkiedy definiuję functorsi POD. W przeciwnym razie używam class.
// '()' is public by default!struct mycompare :public std::binary_function<int,int,bool>{booloperator()(int first,int second){return first < second;}};class mycompare :public std::binary_function<int,int,bool>{public:booloperator()(int first,int second){return first < second;}};
Wszyscy członkowie klasy są domyślnie prywatni, a wszyscy członkowie struktury są domyślnie publiczni. Klasa ma domyślne bazy prywatne, a Struct ma domyślne bazy publiczne. Struct w przypadku C nie może mieć funkcji składowych, przy czym tak jak w przypadku C ++ możemy dodawać funkcje składowe do struktury. Poza tymi różnicami nie znajduję w nich nic zaskakującego.
Używam struct tylko wtedy, gdy muszę przechowywać niektóre dane bez powiązanych z nim funkcji członkowskich (aby operować na danych członka) i uzyskać bezpośredni dostęp do zmiennych danych.
Np .: Odczytywanie / zapisywanie danych z plików i strumieni gniazd itp. Przekazywanie argumentów funkcji w strukturze, w której argumentów funkcji jest zbyt wiele, a składnia funkcji wygląda na zbyt długą.
Technicznie nie ma dużej różnicy między klasą a strukturą, z wyjątkiem domyślnej dostępności. Ponadto zależy od stylu programowania, w jaki sposób go używasz.
Pomyślałem, że Structions ma być strukturą danych (jak tablica informacji zawierająca wiele danych), a klasy były przeznaczone do pakowania kodu (podobnie jak zbiory podprogramów i funkcji).
Nie mogę sobie wyobrazić scenariusza, w którym użyłbyś struktury, gdy chcesz członków prywatnych, chyba że celowo próbujesz być mylący.
Wydaje się, że użycie struktur jest bardziej składniowym wskazaniem, w jaki sposób dane będą wykorzystywane, ale wolałbym po prostu stworzyć klasę i spróbować wyrazić to wyraźnie w nazwie klasy lub poprzez komentarze.
Według mnie „składniowe wskazanie, w jaki sposób dane będą wykorzystywane” jest całkowicie dobrym powodem do użycia struktury, szczególnie jeśli alternatywą jest użycie komentarza lub nazwy w nazwie klasy.
Viktor Sehr
2
Czy stwierdzenie, structże członkowie klasy będą domyślnie publiczni, nie byłoby już jednoznaczne?
Odpowiedzi:
Różnice między
class
aistruct
w C ++ polegają na tym, że struktury mają domyślnepublic
elementy i bazy, a klasy mają domyślneprivate
elementy i bazy. Obie klasy i kodowanym może mieć mieszankępublic
,protected
iprivate
członkowie mogą korzystać z dziedziczenia i mogą mieć funkcje składowe.Poleciłbym używanie struktur jako zwykłych struktur danych bez żadnych funkcji podobnych do klas, i używanie klas jako agregujących struktur
private
danych z danymi i funkcjami składowymi.źródło
Jak wszyscy zauważają, w rzeczywistości istnieją tylko dwie rzeczywiste różnice językowe:
struct
domyślnie dostęp publiczny iclass
domyślny dostęp prywatny.struct
domyślnie przyjmujepublic
dziedziczenie iclass
domyślnieprivate
dziedziczenie. (Jak na ironię, podobnie jak w przypadku wielu rzeczy w C ++, domyślnie jest to wstecz:public
dziedziczenie jest zdecydowanie bardziej powszechnym wyborem, ale ludzie rzadko deklarują,struct
że oszczędzają na wpisaniupublic
słowa kluczowego „ ”.Ale prawdziwa różnica w praktyce między
class
/struct
, który deklaruje konstruktora / destruktora i jeden, który nie. Istnieją pewne gwarancje na POD typu „zwykłe stare dane”, które nie obowiązują już po przejęciu konstrukcji klasy. Aby zachować to rozróżnienie, wiele osób celowo używa tylkostruct
s dla typów POD, a jeśli zamierzają w ogóle dodać jakiekolwiek metody, używająclass
es. Różnica między dwoma fragmentami poniżej jest bez znaczenia:(Nawiasem mówiąc, oto wątek z kilkoma dobrymi objaśnieniami, co tak naprawdę oznacza „typ POD”: Co to są typy POD w C ++? )
źródło
struct
lubclass
nie ma żadnego wpływu na to, czy obiekt POD czy należy zdefiniować konstruktor kopiuj / destruktora. Funkcje składowe również nie mają wpływu na to, że coś jest POD. Kiedy ponownie czytam to, co napisałeś, widzę, że nie sugerujesz inaczej, ale obecne sformułowanie jest myląceIstnieje wiele nieporozumień w istniejących odpowiedziach.
Zarówno
class
istruct
deklarują klasę.Tak, może być konieczne przestawienie słów kluczowych modyfikujących dostęp w definicji klasy, w zależności od słowa kluczowego użytego do zadeklarowania klasy.
Ale poza składnią jedynym powodem, aby wybierać między innymi, jest konwencja / styl / preferencja.
Niektórzy ludzie lubią trzymać się
struct
słowa kluczowego dla klas bez funkcji składowych, ponieważ wynikowa definicja „wygląda jak” prosta struktura z C.Podobnie, niektórzy ludzie lubią używać
class
słowa kluczowego dla klas z funkcjami iprivate
danymi składowymi, ponieważ na nim jest napisane „klasa”, a zatem wyglądają jak przykłady z ich ulubionych książek na temat programowania obiektowego.Rzeczywistość jest taka, że to całkowicie zależy od ciebie i twojego zespołu, i to dosłownie nie zrobi żadnej różnicy dla twojego programu.
Poniższe dwie klasy są absolutnie równoważne pod każdym względem oprócz ich nazwy:
Możesz nawet przełączać słowa kluczowe podczas ponownego tworzenia:
(chociaż powoduje to uszkodzenie kompilacji Visual Studio z powodu niezgodności, więc kompilator wyświetli ostrzeżenie po wykonaniu tej czynności).
a następujące wyrażenia mają wartość true:
Pamiętaj jednak, że nie można zmieniać słów kluczowych podczas redefiniowania ; dzieje się tak tylko dlatego, że (zgodnie z regułą jednej definicji) zduplikowane definicje klas w jednostkach tłumaczeniowych muszą „składać się z tej samej sekwencji tokenów” . Oznacza to, że nie możesz nawet wymieniać
const int member;
sięint const member;
i nie ma to nic wspólnego z semantykąclass
lubstruct
.źródło
class foo { public: ... };
a inna może mieć,struct foo { ... };
co musiałoby być zgodne z twierdzeniem „absolutnie równoważnym”. Chodzi o przyczyny, że niepełne oświadczeniastruct foo;
iclass foo;
są wymienne. Nie określają one treści klasy, więc nie mówią nic o układzie dostępu.Foo
iBar
nadal są równoważne / identyczne typy. Upewniłem się, że powiedziałem „przy ponownym zgłaszaniu ” i podałem przykład. Pomyśl o tym, wyjaśnię to w odpowiedzi, aby upewnić się, że nie wprowadzam ludzi w błąd UBJedynym razem, gdy używam struktury zamiast klasy, jest deklarowanie funktora tuż przed użyciem go w wywołaniu funkcji i chcę zminimalizować składnię ze względu na przejrzystość. na przykład:
źródło
Z C ++ FAQ Lite :
źródło
Jednym z miejsc, w którym struktura była dla mnie pomocna, jest system, który odbiera komunikaty o stałym formacie (np. Port szeregowy) z innego systemu. Możesz rzutować strumień bajtów na strukturę, która definiuje twoje pola, a następnie łatwo uzyskać do nich dostęp.
Oczywiście jest to to samo, co zrobiłbyś w C, ale uważam, że narzut związany z dekodowaniem wiadomości do klasy zwykle nie jest tego wart.
źródło
operator >>
na klasie zamiast pisaćprocessMessage
funkcję, dzięki czemu Twój C ++ będzie wyglądał bardziej jak poprawny C ++, a mniej jak C.__packed__
struktury i mieć implementację ifdef obsługującą endian (musisz zmienić kolejność na komputerze, na którym endianess jest przeciwny do zewnętrznego źródła danych zapewnia). To nie jest ładne, ale zwykłem pakować / rozpakowywać rejestry zdalnych urządzeń peryferyjnych na platformach wbudowanych w przenośny sposób.char
typ, który jest zwolniony z aliasingu. Jednak nadal istnieje problem, choć inny: rzutowaniechar*
na inny typ, jeśli tak naprawdę nie było już żadnego obiektu tego drugiego typu, który został już zainicjowany pod tym adresem, jest UB, ponieważ narusza reguły życia. Afaik, nawet jeśli typ docelowy jest trywialnie konstruowalny, samo przydzielenie pamięci nie jest wystarczające, aby C ++ formalnie pozwalał na traktowanie tej pamięci jako tego typu.Możesz użyć „struct” w C ++, jeśli piszesz bibliotekę, której wewnętrznymi elementami są C ++, ale API można wywoływać za pomocą kodu C lub C ++. Po prostu tworzysz pojedynczy nagłówek, który zawiera struktury i globalne funkcje API, które udostępniasz zarówno kodowi C, jak i C ++ w następujący sposób:
Następnie możesz napisać pasek funkcji () w pliku C ++ za pomocą kodu C ++ i ustawić go jako wywoływalny z C, a dwa światy mogą dzielić dane poprzez zadeklarowane struktury. Istnieją oczywiście inne zastrzeżenia dotyczące mieszania C i C ++, ale jest to uproszczony przykład.
źródło
Jak wszyscy mówią, jedyną prawdziwą różnicą jest domyślny dostęp. Ale szczególnie używam struct, gdy nie chcę żadnego enkapsulacji za pomocą prostej klasy danych, nawet jeśli zaimplementuję jakieś metody pomocnicze. Na przykład, gdy potrzebuję czegoś takiego:
źródło
Aby odpowiedzieć na moje pytanie (bezwstydnie), jak już wspomniano, uprawnienia dostępu są jedyną różnicą między nimi w C ++.
Zwykle używam struktury tylko do przechowywania danych. Pozwolę mu uzyskać kilka funkcji pomocniczych, jeśli ułatwi to pracę z danymi. Jednak gdy tylko dane wymagają kontroli przepływu (tj. Pobierające / ustawiające, które utrzymują lub chronią stan wewnętrzny) lub zaczynają uzyskiwać jakąkolwiek większą funkcjonalność (zasadniczo bardziej obiektową), zostaną „uaktualnione” do klasy, aby lepiej komunikować zamiary.
źródło
Struktury ( POD , bardziej ogólnie) są przydatne, gdy zapewniasz interfejs kompatybilny z C z implementacją C ++, ponieważ są one przenośne ponad granicami języków i formatami linkerów.
Jeśli to nie dotyczy ciebie, to przypuszczam, że użycie „struct” zamiast „class” jest dobrym komunikatorem intencji (jak wspomniano powyżej @ ZeroSignal). Struktury mają również bardziej przewidywalną semantykę kopiowania, więc są przydatne w przypadku danych, które zamierzasz zapisać na nośniku zewnętrznym lub przesłać przewodowo.
Struktury są również przydatne do różnych zadań metaprogramowania, takich jak szablony cech, które po prostu ujawniają kilka zależnych typów typów:
... Ale tak naprawdę to korzysta z domyślnego poziomu ochrony structa, który jest publiczny ...
źródło
W przypadku C ++ naprawdę nie ma dużej różnicy między strukturami a klasami. Główną różnicą funkcjonalną jest to, że członkowie struktury są domyślnie publiczni, podczas gdy domyślnie są prywatni w klasach. W przeciwnym razie, jeśli chodzi o język, są one równoważne.
To powiedziawszy, zwykle używam struktur w C ++, tak jak robię to w C #, podobnie jak powiedział Brian. Struktury są prostymi kontenerami danych, podczas gdy klasy są używane dla obiektów, które muszą oddziaływać na dane oprócz tylko ich trzymania.
źródło
Są prawie takie same. Dzięki magii C ++, struct może przechowywać funkcje, używać dziedziczenia, tworzone przy użyciu „new” i tak dalej jak klasa
Jedyną różnicą funkcjonalną jest to, że klasa zaczyna się od prywatnych praw dostępu, a struct zaczyna się od public. Jest to zachowanie zgodności wstecznej z C.
W praktyce zawsze używałem struktur jako posiadaczy danych, a klas jako obiektów.
źródło
Jak zauważyli inni
Istnieje wyraźne zalecenie dotyczące tego, kiedy stosować Stroustrup / Sutter:
Pamiętaj jednak, że nie jest mądre przekazywanie dalej czegoś. jako class (
class X;
) i zdefiniuj go jako struct (struct X { ... }
). Może działać na niektórych linkerach (np. G ++) i może zawieść na innych (np. MSVC), więc znajdziesz się w piekle programisty.źródło
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
nie tylko kompiluje się i działa z MSVC 2017, ale nawet tworzy wyraźne ostrzeżenie, któreFoo
zostało zadeklarowane jakostruct
zdefiniowane jakoclass
. Ale pamiętam też wyraźnie, że znalezienie tego głupiego robaka kosztowało nasz zespół pół dnia. Nie jestem pewien, jakiej wersji MSVC używaliśmy wtedy.class
lubstruct
na przednim deklaracji, a dwa są swobodnie wymienialne na standardzie (choć wiadomo, że VS ostrzega, zawsze zakłada się, że właśnie w celu uniknięcia widocznych błędów programista). Coś tu nie pachnie. Czy na pewno nie był to błąd naruszenia ODR?struct
Forward na-class
Forward, problemy zniknęły. Na dzień dzisiejszy też wydaje mi się to dziwne. Byłbym zadowolony, gdybyś mógł rzucić na to trochę światła.Klasa.
Członkowie klasy są domyślnie prywatni.
Jest równa
Więc jeśli spróbujesz
Otrzymamy błąd:
main_one is private
ponieważ nie jest dostępny. Możemy go rozwiązać, inicjując go, określając go jako publiczny, tjStruct.
Struktura to klasa, w której członkowie są domyślnie publiczni.
Środki
main_one
są prywatne tjUżywam struktur do struktur danych, w których członkowie mogą przyjmować dowolną wartość, w ten sposób jest łatwiej.
źródło
Zaletą
struct
przezclass
to, że uratować jedną linię kodu, jeśli przylegającą do „pierwszych członków publicznych, następnie prywatna”. W tym świetle znajduję słowo kluczoweclass
bezużyteczne.Oto kolejny powód używania tylko
struct
i nigdyclass
. Niektóre wytyczne dotyczące stylu kodu dla C ++ sugerują używanie małych liter w makrach funkcyjnych, uzasadnieniem jest to, że kiedy makro jest konwertowane na funkcję wbudowaną, nazwa nie powinna wymagać zmiany. To samo tutaj. Masz swoją ładną strukturę w stylu C i pewnego dnia dowiadujesz się, że musisz dodać konstruktor lub jakąś wygodną metodę. Czy zmienisz to naclass
? Wszędzie?Rozróżnianie
struct
s orazclass
es jest po prostu zbyt wiele kłopotów, dostając w zasadzie robi to, co powinniśmy robić - programowanie. Podobnie jak wiele problemów C ++, wynika on z silnego pragnienia wstecznej kompatybilności.źródło
class
? Czy uważasz, że klasa zdefiniowana za pomocąstruct
słowa kluczowego nie może mieć funkcji członka ani konstruktora?joe()
musi być zdefiniowana za pomocąclass
słowa kluczowego? Każda klasa z co najmniej 4int
członkami musi być zdefiniowana za pomocąstruct
słowa kluczowego?struct
, agregaty metodami są zdefiniowane za pomocąclass
”. Za dużo kłopotów.są takie same z różnymi ustawieniami domyślnymi (domyślnie prywatne
class
i publiczne dlastruct
), więc teoretycznie są one całkowicie wymienne.więc jeśli chcę tylko spakować jakieś informacje, aby się poruszać, używam struktury, nawet jeśli podam tam kilka metod (ale nie wiele). Jeśli jest to w większości nieprzejrzyste, gdzie głównym zastosowaniem byłyby metody, a nie bezpośrednio członkowie danych, używam pełnej klasy.
źródło
Struktury domyślnie mają dostęp publiczny, a klasy domyślnie mają dostęp prywatny.
Osobiście używam struktur do przenoszenia danych lub jako obiektów wartości. W takim przypadku deklaruję wszystkich członków jako const, aby zapobiec modyfikacji przez inny kod.
źródło
Zarówno
struct
iclass
są takie same pod maską choć z różnych domyślnych co do widoczności,struct
domyślnie jest publiczny iclass
domyślnie jest prywatny. Możesz zmienić jedno z nich, używając odpowiednioprivate
ipublic
. Obie pozwalają na dziedziczenie, metody, konstruktory, destruktory i wszystkie inne zalety języka zorientowanego obiektowo.Jednak jedna ogromna różnica między nimi polega na tym, że
struct
słowo kluczowe jest obsługiwane w języku C, podczas gdyclass
nie. Oznacza to, że można używaćstruct
w include pliku, który można#include
w każdej C ++ lub C tak długo, jakstruct
to zwykły C stylstruct
i wszystko w include plik jest kompatybilny z C, to znaczy nie C ++ konkretne słowa kluczowe, takie jakprivate
,public
nie metody, brak dziedziczenia itp. itd. itd.Styl AC
struct
może być używany z innymi interfejsami, które obsługują styl Cstruct
do przenoszenia danych tam iz powrotem przez interfejs.Styl AC
struct
to rodzaj szablonu (nie szablon C ++, ale raczej wzór lub szablon), który opisuje układ obszaru pamięci. Z biegiem lat interfejsy użytkowej z C i C wtyczek (tu patrzy na ciebie Java i Python i Visual Basic) zostały stworzone z których niektóre prace z klasą Cstruct
.źródło
Technicznie oba są takie same w C ++ - na przykład istnieje możliwość przeciążenia operatorów przez strukturę itp.
Jednak :
Używam struktur, gdy chcę przekazywać informacje wielu typów jednocześnie. Korzystam z klas, gdy mam do czynienia z „funkcjonalnym” obiektem.
Mam nadzieję, że to pomoże.
Na przykład zwracam tutaj ucznia strukturalnego metodami get ... () tutaj - baw się dobrze.
źródło
Używam,
struct
kiedy definiujęfunctors
iPOD
. W przeciwnym razie używamclass
.źródło
std::binary_function<>
nie jest po prostu przestarzała, c ++ 17 nawet ją usuwa.Używam struktur, gdy muszę utworzyć typ POD lub funktor.
źródło
Wszyscy członkowie klasy są domyślnie prywatni, a wszyscy członkowie struktury są domyślnie publiczni. Klasa ma domyślne bazy prywatne, a Struct ma domyślne bazy publiczne. Struct w przypadku C nie może mieć funkcji składowych, przy czym tak jak w przypadku C ++ możemy dodawać funkcje składowe do struktury. Poza tymi różnicami nie znajduję w nich nic zaskakującego.
źródło
Używam struct tylko wtedy, gdy muszę przechowywać niektóre dane bez powiązanych z nim funkcji członkowskich (aby operować na danych członka) i uzyskać bezpośredni dostęp do zmiennych danych.
Np .: Odczytywanie / zapisywanie danych z plików i strumieni gniazd itp. Przekazywanie argumentów funkcji w strukturze, w której argumentów funkcji jest zbyt wiele, a składnia funkcji wygląda na zbyt długą.
Technicznie nie ma dużej różnicy między klasą a strukturą, z wyjątkiem domyślnej dostępności. Ponadto zależy od stylu programowania, w jaki sposób go używasz.
źródło
Pomyślałem, że Structions ma być strukturą danych (jak tablica informacji zawierająca wiele danych), a klasy były przeznaczone do pakowania kodu (podobnie jak zbiory podprogramów i funkcji).
:(
źródło
Nigdy nie używam „struct” w C ++.
Nie mogę sobie wyobrazić scenariusza, w którym użyłbyś struktury, gdy chcesz członków prywatnych, chyba że celowo próbujesz być mylący.
Wydaje się, że użycie struktur jest bardziej składniowym wskazaniem, w jaki sposób dane będą wykorzystywane, ale wolałbym po prostu stworzyć klasę i spróbować wyrazić to wyraźnie w nazwie klasy lub poprzez komentarze.
Na przykład
źródło
struct
że członkowie klasy będą domyślnie publiczni, nie byłoby już jednoznaczne?