Quando dovresti usare una class vs una struct in C ++?

In quali scenari è meglio usare una struct vs una class in C ++?

Le differenze tra una class e una struct in C ++ sono che le strutture hanno membri public predefiniti e le basi e le classi hanno membri e basi private predefiniti. Entrambe le classi e le strutture possono avere una combinazione di membri public , protected e private , possono utilizzare l’ereditarietà e possono avere funzioni membro.

Raccomanderei di utilizzare le strutture come strutture plain-old-data senza caratteristiche di class e utilizzare classi come strutture di dati aggregate con dati private e funzioni membro.

Come notano tutti gli altri, ci sono solo due differenze linguistiche reali:

  • struct impostazione predefinita l’accesso pubblico e class impostazioni predefinite di class per l’accesso privato.
  • Quando si eredita, struct impostazione predefinita public ereditarietà public e class impostazioni predefinite di class sull’ereditarietà private . (Ironia della sorte, come con così tante cose in C ++, il default è retrocesso: public ereditarietà public è di gran lunga la scelta più comune, ma le persone dichiarano raramente le struct solo per risparmiare digitando la parola chiave ” public “.

Ma la vera differenza nella pratica è tra una class / struct che dichiara un costruttore / distruttore e uno che non lo fa. Ci sono certe garanzie per un tipo di POD “plain-old-data”, che non si applicano più una volta che tu prendi il controllo della costruzione della class. Per mantenere questa distinzione chiara, molte persone usano deliberatamente solo struct per i tipi di POD e, se stanno per aggiungere qualsiasi metodo, usano le class . La differenza tra i due frammenti di seguito è altrimenti priva di significato:

 class X { public: // ... }; struct X { // ... }; 

(Per inciso, ecco una discussione con alcune buone spiegazioni su cosa significa in realtà “tipo POD”: quali sono i tipi di POD in C ++? )

Ci sono molti malintesi nelle risposte esistenti.

Sia la class che la struct dichiarano una class.

Sì, potrebbe essere necessario riorganizzare le parole chiave di modifica dell’accesso all’interno della definizione della class, in base alla parola chiave utilizzata per dichiarare la class.

Ma, al di là della syntax, l’ unica ragione per scegliere l’una rispetto all’altra è convenzione / stile / preferenza.

Ad alcune persone piace attenersi alla parola chiave struct per le classi senza funzioni membro, perché la definizione risultante “assomiglia” ad una struttura semplice da C.

Allo stesso modo, ad alcune persone piace usare la parola chiave class per le classi con funzioni membro e dati private , perché dice “class” su di esso e quindi assomiglia ad esempi tratti dal loro libro preferito sulla programmazione orientata agli oggetti.

La realtà è che dipende completamente da te e dal tuo team, e non farà letteralmente alcuna differenza per il tuo programma.

Le seguenti due classi sono assolutamente equivalenti in tutti i modi tranne il loro nome:

 struct Foo { int x; }; class Bar { public: int x; }; 

Puoi persino cambiare parola chiave durante la ridichiarazione:

 class Foo; struct Bar; 

(anche se alcuni compilatori emetteranno un avvertimento quando lo farai, supponendo che probabilmente non hai intenzione di fare qualcosa di così confuso e che dovresti quindi essere invitato a ricontrollare il tuo codice.)

e le seguenti espressioni valgono entrambe per vero:

 std::is_class::value std::is_class::value 

Si noti, tuttavia, che non è ansible cambiare le parole chiave durante la ridefinizione ; questo è solo perché (secondo la regola a una definizione) le definizioni di classi duplicate tra le unità di traduzione devono “consistere della stessa sequenza di token” . Questo significa che non puoi nemmeno scambiare un const int member; con int const member; e non ha nulla a che fare con la semantica della class o della struct .

L’unica volta che uso una struct al posto di una class è quando dichiaro un functor prima di usarlo in una chiamata di funzione e voglio minimizzare la syntax per chiarezza. per esempio:

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

Dalle domande frequenti su C ++ Lite :

I membri e le classi base di una struct sono pubblici per impostazione predefinita, mentre in class, per impostazione predefinita sono privati. Nota: dovresti rendere le tue classi base esplicitamente pubbliche, private o protette, piuttosto che fare affidamento sui valori predefiniti.

struct e class sono altrimenti funzionalmente equivalenti.

OK, abbastanza di quel chiacchiericcio pulito e techno. Emotivamente, la maggior parte degli sviluppatori fa una forte distinzione tra una class e una struttura. Una struttura si sente semplicemente come una pila aperta di bit con pochissimo in termini di incapsulamento o funzionalità. Una class si sente come un membro vivo e responsabile della società con servizi intelligenti, una forte barriera di incapsulamento e un’interfaccia ben definita. Poiché questa è la connotazione che la maggior parte delle persone già possiede, dovresti probabilmente usare la parola chiave struct se hai una class che ha pochissimi metodi e ha dati pubblici (cose del genere esistono in sistemi ben progettati!), Ma altrimenti dovresti probabilmente usare la class parola chiave.

Un posto in cui una struttura è stata utile per me è quando ho un sistema che riceve messaggi di formato fisso (per esempio, una porta seriale) da un altro sistema. È ansible eseguire il cast del stream di byte in una struttura che definisce i campi e quindi accedere facilmente ai campi.

 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); } 

Ovviamente, questa è la stessa cosa che faresti in C, ma trovo che il sovraccarico di dover decodificare il messaggio in una class di solito non ne valga la pena.

Puoi usare “struct” in C ++ se stai scrivendo una libreria i cui interni sono C ++, ma l’API può essere chiamata dal codice C o C ++. È sufficiente creare una singola intestazione che contiene le strutture e le funzioni API globali che si espongono al codice C e C ++ in questo modo:

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

Quindi puoi scrivere una barra delle funzioni () in un file C ++ usando il codice C ++ e renderlo richiamabile da C e i due mondi possono condividere i dati attraverso le strutture dichiarate. Ci sono altri avvertimenti, ovviamente, quando si mescolano C e C ++, ma questo è un esempio semplificato.

Come tutti dicono, l’unica vera differenza è l’accesso predefinito. Ma io uso in particolare struct quando non voglio alcun tipo di incapsulamento con una semplice class di dati, anche se implemento alcuni metodi di supporto. Ad esempio, quando ho bisogno di qualcosa del genere:

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

Le strutture ( POD , più in generale) sono utili quando si fornisce un’interfaccia C compatibile con un’implementazione C ++, poiché sono trasferibili attraverso i confini linguistici e i formati di linker.

Se questo non ti riguarda, allora suppongo che l’uso della “struct” anziché di “class” sia un buon comunicatore di intenti (come detto in precedenza da @ZeroSignal). Le strutture hanno anche una semantica di copia più prevedibile, quindi sono utili per i dati che si intende scrivere su supporti esterni o inviati attraverso il filo.

Le strutture sono anche utili per varie attività di metaprogrammazione, come i modelli di tratti che espongono un gruppo di typedef dipendenti:

 template  struct type_traits { typedef T type; typedef T::iterator_type iterator_type; ... }; 

… Ma questo è solo sfruttando il livello di protezione predefinito di struct come pubblico …

Per C ++, non c’è davvero molta differenza tra le strutture e le classi. La principale differenza funzionale è che i membri di una struct sono pubblici per impostazione predefinita, mentre sono privati ​​per impostazione predefinita nelle classi. Altrimenti, per quanto riguarda la lingua, sono equivalenti.

Detto questo, tendo ad usare le strutture in C ++ come faccio in C #, in modo simile a quello che Brian ha detto. Le strutture sono semplici contenitori di dati, mentre le classi vengono utilizzate per oggetti che devono agire sui dati oltre a limitarsi a tenerli.

Per rispondere alla mia domanda (senza vergogna), come già accennato, i privilegi di accesso sono l’unica differenza tra loro in C ++.

Tendo a usare solo una struttura per la memorizzazione dei dati. Gli permetterò di ottenere alcune funzioni di aiuto se renderà più facile lavorare con i dati. Tuttavia, non appena i dati richiedono il controllo del stream (cioè getter / setter che mantengono o proteggono uno stato interno) o iniziano ad accedere a qualsiasi funzionalità principale (sostanzialmente più simile ad un object), verranno “aggiornati” in una class per comunicare meglio l’intento.

Sono praticamente la stessa cosa. Grazie alla magia del C ++, una struct può contenere funzioni, usare l’ereditarietà, creare usando “nuovo” e così via proprio come una class

L’unica differenza funzionale è che una class inizia con i diritti di accesso privati, mentre una struttura inizia con il pubblico. Questa è la compatibilità con le versioni precedenti con C.

In pratica, ho sempre usato le strutture come titolari di dati e classi come oggetti.

Classe.

I membri della class sono privati ​​per impostazione predefinita.

 class test_one { int main_one(); }; 

È equivalente a

 class test_one { private: int main_one(); }; 

Quindi se ci provi

 int two = one.main_one(); 

main_one is private un errore: main_one is private perché non accessibile. Possiamo risolverlo inizializzandolo specificandone un pubblico, ad es

 class test_one { public: int main_one(); }; 

Struct.

Una struct è una class in cui i membri sono pubblici per impostazione predefinita.

 struct test_one { int main_one; }; 

Mezzi main_one è privato ie

 class test_one { public: int main_one; }; 

Uso le strutture per le strutture di dati in cui i membri possono assumere qualsiasi valore, è più facile in questo modo.

sono la stessa cosa con diverse impostazioni predefinite (private di default per la class e public di default per struct ), quindi in teoria sono totalmente intercambiabili.

quindi, se voglio solo impacchettare alcune informazioni per spostarmi, uso una struct, anche se inserisco alcuni metodi lì (ma non molti). Se si tratta di una cosa per lo più opaca, in cui l’uso principale sarebbe attraverso i metodi, e non direttamente ai membri dei dati, io uso una class completa.

Le strutture di default hanno accesso pubblico e le classi hanno per impostazione predefinita accesso privato.

Personalmente utilizzo le strutture per gli oggetti Data Transfer o come oggetti valore. Se usato come tale, dichiaro tutti i membri come const per impedire modifiche con altri codici.

Tecnicamente, entrambi sono uguali in C ++ – ad esempio è ansible che una struttura abbia operatori sovraccaricati ecc.

Però :

Uso le structs quando desidero passare informazioni di più tipi contemporaneamente uso le classi quando ho a che fare con un object “funzionale”.

Spero che sia d’aiuto.

 #include  #include  using namespace std; struct student { int age; string name; map grades }; class ClassRoom { typedef map 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; }; 

Per esempio, sto restituendo una struttura studentesca nei metodi get … () qui – divertiti.

Quando sceglieresti di usare struct e quando usare la class in C ++?

Io uso struct quando definisco i functors e il POD . Altrimenti uso la class .

 // '()' is public by default! struct mycompare : public std::binary_function { bool operator()(int first, int second) { return first < second; } }; class mycompare : public std::binary_function { public: bool operator()(int first, int second) { return first < second; } }; 

Io uso le strutture quando ho bisogno di creare il tipo POD o il functor.

Un vantaggio di struct over class è che salva una riga di codice, se aderisce a “first public members, then private”. In questa luce, trovo la class parole chiave inutile.

Ecco un’altra ragione per usare solo struct e mai class . Alcune linee guida sullo stile del codice per C ++ suggeriscono l’uso di lettere minuscole per macro di funzione, la logica è che quando la macro viene convertita in una funzione inline, il nome non deve essere modificato. Anch’io. Hai la tua bella struttura in stile C e un giorno, scopri che è necessario aggiungere un costruttore o un metodo di convenienza. Lo cambi in una class ? Ovunque?

Distinguere tra le struct e le class è un problema troppo grande, intromettersi nel fare ciò che dovremmo fare, la programmazione. Come molti dei problemi del C ++, nasce dal forte desiderio di retrocompatibilità.

Uso struct solo quando è necessario conservare alcuni dati senza alcuna funzione membro associata (per operare sui dati membro) e accedere direttamente alle variabili dei dati.

Ad esempio: lettura / scrittura di dati da file e stream di socket ecc. Passando gli argomenti della funzione in una struttura in cui gli argomenti della funzione sono troppi e la syntax della funzione sembra troppo lunga.

Tecnicamente non vi è alcuna grande differenza tra la class e il supporto, tranne l’accessibilità predefinita. Più sopra dipende dallo stile di programmazione come lo si utilizza.

Pensavo che Structs fosse inteso come una struttura dati (come una matrice di informazioni di tipo multi-dati) e che le classi fossero intese per il Code Packaging (come le raccolte di subroutine e funzioni).

🙁

Non uso mai “struct” in C ++.

Non riesco mai a immaginare uno scenario in cui useresti una struttura quando vuoi membri privati, a meno che tu non stia volutamente cercando di essere confuso.

Sembra che usare le strutture sia più un’indicazione sintattica di come i dati saranno usati, ma preferirei semplicemente creare una class e provare a renderla esplicita nel nome della class, o attraverso i commenti.

Per esempio

 class PublicInputData { //data members }; 

Le funzioni di accesso non sono l’unica differenza tra le strutture e le classi. Una struct è migliore per i tipi POD (Plain Old Data), poiché è più facile da gestire per il compilatore e il programmatore. Per i principianti che non usano la programmazione orientata agli oggetti, l’uso di una struct va bene.