Kiedy należy używać klasy w porównaniu do struktury w C ++?


949

W jakich scenariuszach lepiej jest używać structvs classw C ++?


47
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.


99
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.

Zarówno classi structdeklarują 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ę 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:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

Możesz nawet przełączać słowa kluczowe podczas ponownego tworzenia:

class Foo;
struct Bar;

(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:

std::is_class<Foo>::value
std::is_class<Bar>::value

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.


15
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:

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 

35
Teraz, gdy jest kilka lat później, a C ++ 11 jest obsługiwany przez wszystkie główne kompilatory, Lambdas czyni to jeszcze bardziej zwięzłym .

36

Z C ++ FAQ Lite :

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.


1
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.

typedef struct
{
    int messageId;
    int messageCounter;
    int messageData;
} tMessageType;

void processMessage(unsigned char *rawMessage)
{
    tMessageType *messageFields = (tMessageType *)rawMessage;
    printf("MessageId is %d\n", messageFields->messageId);
}

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.


To samo można osiągnąć w C.
Eugene Bujak,

11
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 here
struct foo
{
    ...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;

// Put your C API functions here
void 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.


2
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:

struct myvec {
    int x;
    int y;
    int z;

    int length() {return x+y+z;}
};

1
+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.


9

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 ...


1
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.


4

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.


4

Jak zauważyli inni

  • oba są równoważne oprócz domyślnej widoczności
  • mogą istnieć powody, aby być zmuszonym do korzystania z jednego lub drugiego z dowolnego powodu

Istnieje wyraźne zalecenie dotyczące tego, kiedy stosować Stroustrup / Sutter:

Użyj klasy, jeśli klasa ma niezmiennik; użyj struct, jeśli elementy danych mogą się różnić niezależnie

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.


Czy możesz opisać te problemy z linkerem?
Wyścigi lekkości na orbicie

@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?
Wyścigi lekkości na orbicie


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.


3

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.


2

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.


2

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.


1

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.

#include <string>
#include <map>
using namespace std;

struct student
{
    int age;
    string name;
    map<string, int> grades
};

class ClassRoom
{
    typedef map<string, student> student_map;
  public :
    student getStudentByName(string name) const 
    { student_map::const_iterator m_it = students.find(name); return m_it->second; }
  private :
    student_map students;
};

Na przykład zwracam tutaj ucznia strukturalnego metodami get ... () tutaj - baw się dobrze.


1

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>
{
    bool operator()(int first, int second)
    { return first < second; }
};

class mycompare : public std::binary_function<int, int, bool>
{
public:
    bool operator()(int first, int second)
    { return first < second; }
};

1
Ta odpowiedź wykazuje oznaki wieku :) std::binary_function<>nie jest po prostu przestarzała, c ++ 17 nawet ją usuwa.
patrz

Nic dziwnego, odkąd został napisany w C ++ 03, języku zdefiniowanym 15 lat temu.
Wyścigi lekkości na orbicie


1

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.


0

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.


-4

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).

:(


-6

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

class PublicInputData {
    //data members
 };

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?
wrongusername
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.