In welchen Szenarien ist es besser, a struct
vs a class
in C ++ zu verwenden?
In welchen Szenarien ist es besser, a struct
vs a class
in C ++ zu verwenden?
Antworten:
Unterschiede zwischen a class
und a struct
in C ++ bestehen darin, dass Strukturen Standardelemente public
und Basen haben und Klassen Standardelemente private
und Basen haben. Beiden Klassen und Strukturen können eine Mischung aus haben public
, protected
und private
Mitglieder können Vererbung verwenden und können Elementfunktionen haben.
Ich würde empfehlen, Strukturen als einfache alte Datenstrukturen ohne klassenähnliche Merkmale und Klassen als aggregierte Datenstrukturen mit private
Daten- und Elementfunktionen zu verwenden .
Wie alle anderen bemerken, gibt es wirklich nur zwei tatsächliche Sprachunterschiede:
struct
Standardmäßig wird der öffentliche Zugriff und class
standardmäßig der private Zugriff verwendet.struct
standardmäßig die public
Vererbung und class
standardmäßig die private
Vererbung verwendet. (Ironischerweise ist, wie bei so vielen Dingen in C ++, die Standardeinstellung rückwärts: public
Vererbung ist bei weitem die häufigere Wahl, aber die Leute erklären selten struct
s, nur um beim Eingeben des public
Schlüsselworts " " zu sparen .Der wirkliche Unterschied in der Praxis besteht jedoch zwischen einem class
/ struct
, das einen Konstruktor / Destruktor deklariert, und einem, der dies nicht tut. Es gibt bestimmte Garantien für einen POD-Typ mit "einfachen alten Daten", die nicht mehr gelten, sobald Sie die Konstruktion der Klasse übernehmen. Um diese Unterscheidung klar zu halten, verwenden viele Menschen struct
s absichtlich nur für POD-Typen und verwenden es, wenn sie überhaupt Methoden hinzufügen wollen class
. Der Unterschied zwischen den beiden folgenden Fragmenten ist ansonsten bedeutungslos:
class X
{
public:
// ...
};
struct X
{
// ...
};
(Übrigens, hier ist ein Thread mit einigen guten Erklärungen darüber, was "POD-Typ" eigentlich bedeutet: Was sind POD-Typen in C ++? )
struct
oder class
keinen Einfluss darauf haben, ob Ihr Objekt POD ist oder ob Sie einen Kopierkonstruktor / Destruktor definieren sollten. Mitgliedsfunktionen haben auch keinen Einfluss darauf, dass etwas POD ist. Als ich noch einmal lese, was Sie geschrieben haben, sehe ich, dass Sie nichts anderes vorschlagen, aber der aktuelle Wortlaut ist verwirrend
Die vorhandenen Antworten enthalten viele Missverständnisse.
Beides class
und struct
deklariere eine Klasse.
Ja, möglicherweise müssen Sie Ihre Schlüsselwörter zum Ändern des Zugriffs innerhalb der Klassendefinition neu anordnen, je nachdem, mit welchem Schlüsselwort Sie die Klasse deklariert haben.
Über die Syntax hinaus ist der einzige Grund, einen über den anderen zu wählen, Konvention / Stil / Präferenz.
Einige Leute halten sich gerne an das struct
Schlüsselwort für Klassen ohne Elementfunktionen, da die resultierende Definition wie eine einfache Struktur aus C aussieht.
In ähnlicher Weise verwenden einige Leute das class
Schlüsselwort gerne für Klassen mit Elementfunktionen und private
Daten, da dort "Klasse" steht und daher wie Beispiele aus ihrem Lieblingsbuch über objektorientierte Programmierung aussieht.
Die Realität ist, dass dies ganz bei Ihnen und Ihrem Team liegt und buchstäblich keinen Unterschied für Ihr Programm macht.
Die folgenden zwei Klassen sind bis auf ihren Namen in jeder Hinsicht absolut gleichwertig:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
Sie können sogar Schlüsselwörter wechseln, wenn Sie neu deklarieren:
class Foo;
struct Bar;
(Obwohl dies die Erstellung von Visual Studio-Builds aufgrund von Nichtkonformität unterbricht, gibt der Compiler dabei eine Warnung aus.)
und die folgenden Ausdrücke werden beide als wahr ausgewertet:
std::is_class<Foo>::value
std::is_class<Bar>::value
Beachten Sie jedoch, dass Sie die Schlüsselwörter bei der Neudefinition nicht wechseln können . Dies liegt nur daran, dass (gemäß der Ein-Definitions-Regel) doppelte Klassendefinitionen über Übersetzungseinheiten hinweg "aus derselben Folge von Token bestehen müssen" . Das heißt , Sie können nicht einmal austauschen const int member;
mit int const member;
, und haben nichts mit der Semantik zu tun class
oder struct
.
class foo { public: ... };
und eine andere struct foo { ... };
, die gemäß der "absolut äquivalenten" Behauptung gelten müsste. Es liegt auf der Hand, dass die unvollständigen Erklärungen struct foo;
und class foo;
austauschbar sind. Diese geben den Klassenkörper nicht an und sprechen daher nichts für das Zugriffslayout.
Foo
und Bar
sind immer noch äquivalente / identische Typen. Ich habe darauf geachtet , "beim erneuten Deklarieren " zu sagen und ein Beispiel zu geben. Wenn ich darüber nachdenke, werde ich dies in der Antwort klarstellen, um sicherzustellen, dass ich die Leute nicht zu UB
Ich verwende eine Struktur nur anstelle einer Klasse, wenn ich einen Funktor deklariere, bevor ich ihn in einem Funktionsaufruf verwende, und aus Gründen der Übersichtlichkeit die Syntax minimieren möchte. z.B:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
Aus dem C ++ FAQ Lite :
Die Mitglieder und Basisklassen einer Struktur sind standardmäßig öffentlich, während sie in der Klasse standardmäßig privat sind. Hinweis: Sie sollten Ihre Basisklassen explizit öffentlich, privat oder geschützt machen, anstatt sich auf die Standardeinstellungen zu verlassen.
Struktur und Klasse sind ansonsten funktional äquivalent.
OK, genug von diesem blitzsauberen Techno-Gerede. Emotional unterscheiden die meisten Entwickler stark zwischen einer Klasse und einer Struktur. Eine Struktur fühlt sich einfach wie ein offener Stapel von Bits an, der nur sehr wenig Kapselung oder Funktionalität bietet. Eine Klasse fühlt sich wie ein lebendiges und verantwortungsbewusstes Mitglied der Gesellschaft mit intelligenten Diensten, einer starken Verkapselungsbarriere und einer klar definierten Schnittstelle. Da dies die Konnotation ist, die die meisten Leute bereits haben, sollten Sie wahrscheinlich das Schlüsselwort struct verwenden, wenn Sie eine Klasse haben, die nur sehr wenige Methoden und öffentliche Daten enthält (solche Dinge existieren in gut gestalteten Systemen!), Aber ansonsten sollten Sie wahrscheinlich die Klasse verwenden Stichwort.
Ein Ort, an dem eine Struktur für mich hilfreich war, ist, wenn ich ein System habe, das Nachrichten mit festem Format (z. B. eine serielle Schnittstelle) von einem anderen System empfängt. Sie können den Bytestrom in eine Struktur umwandeln, die Ihre Felder definiert, und dann einfach auf die Felder zugreifen.
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);
}
Natürlich ist dies das gleiche, was Sie in C tun würden, aber ich finde, dass sich der Aufwand, die Nachricht in eine Klasse dekodieren zu müssen, normalerweise nicht lohnt.
operator >>
eine Klasse implementieren, anstatt die processMessage
Funktion zu schreiben , wodurch Ihr C ++ eher wie richtiges C ++ und weniger wie C aussieht.
__packed__
Struktur verwenden und über eine endian-fähige ifdef-Implementierung verfügen (Sie müssen die Reihenfolge auf einem Computer umkehren, auf dem die Endianess der externen Datenquelle entgegengesetzt ist bietet). Es ist nicht schön, aber ich habe Register für Remote-Peripheriegeräte auf eingebetteten Plattformen auf tragbare Weise gepackt / entpackt.
char
Typ ist, der vom Aliasing ausgenommen ist. Es gibt jedoch immer noch ein Problem, wenn auch ein anderes: Das Umwandeln eines char*
in einen anderen Typ, wenn an dieser Adresse nicht wirklich ein Objekt des letzteren Typs bereits initialisiert wurde, ist UB, da es gegen die Lebensdauerregeln verstößt. Afaik, selbst wenn der Zieltyp trivial konstruierbar ist, reicht es für C ++ nicht aus, nur Speicher zuzuweisen, um diesen Speicher formal als diesen Typ zu behandeln.
Sie können "struct" in C ++ verwenden, wenn Sie eine Bibliothek schreiben, deren Interna C ++ sind, die API jedoch entweder von C- oder C ++ - Code aufgerufen werden kann. Sie erstellen einfach einen einzelnen Header, der Strukturen und globale API-Funktionen enthält, die Sie sowohl C- als auch C ++ - Code wie folgt aussetzen:
// 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
Dann können Sie eine Funktionsleiste () in eine C ++ - Datei mit C ++ - Code schreiben und von C aus aufrufen, und die beiden Welten können Daten über die deklarierten Strukturen gemeinsam nutzen. Es gibt natürlich andere Einschränkungen beim Mischen von C und C ++, aber dies ist ein vereinfachtes Beispiel.
Wie jeder sagt, ist der einzige wirkliche Unterschied der Standardzugriff. Aber ich benutze struct besonders, wenn ich keine Kapselung mit einer einfachen Datenklasse möchte, selbst wenn ich einige Hilfsmethoden implementiere. Zum Beispiel, wenn ich so etwas brauche:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
Um meine eigene Frage zu beantworten (schamlos): Wie bereits erwähnt, sind Zugriffsrechte der einzige Unterschied zwischen ihnen in C ++.
Ich neige dazu, eine Struktur nur zur Datenspeicherung zu verwenden. Ich werde zulassen, dass es einige Hilfsfunktionen erhält, wenn es die Arbeit mit den Daten erleichtert. Sobald die Daten jedoch eine Flusskontrolle erfordern (dh Getter / Setter, die einen internen Zustand beibehalten oder schützen) oder wichtige Funktionen erwerben (im Grunde genommen objektähnlicher), werden sie zu einer Klasse "aktualisiert", um die Absicht besser zu kommunizieren.
Strukturen ( PODs im Allgemeinen) sind praktisch, wenn Sie eine C-kompatible Schnittstelle mit einer C ++ - Implementierung bereitstellen, da sie über Sprachgrenzen und Linkerformate hinweg portierbar sind.
Wenn Ihnen das nichts ausmacht, ist die Verwendung von "struct" anstelle von "class" vermutlich ein guter Kommunikator der Absicht (wie @ZeroSignal oben sagte). Strukturen haben auch eine vorhersehbarere Kopiersemantik, sodass sie für Daten nützlich sind, die Sie auf externe Medien schreiben oder über das Kabel senden möchten.
Strukturen eignen sich auch für verschiedene Metaprogrammieraufgaben, z. B. für Vorlagen für Merkmale, die nur eine Reihe abhängiger Typedefs verfügbar machen:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
... Aber das nutzt wirklich nur den Vorteil, dass die Standardschutzstufe von struct öffentlich ist ...
Für C ++ gibt es wirklich keinen großen Unterschied zwischen Strukturen und Klassen. Der Hauptfunktionsunterschied besteht darin, dass Mitglieder einer Struktur standardmäßig öffentlich sind, während sie in Klassen standardmäßig privat sind. Ansonsten sind sie sprachlich gleichwertig.
Trotzdem neige ich dazu, Strukturen in C ++ zu verwenden, wie ich es in C # tue, ähnlich wie Brian es gesagt hat. Strukturen sind einfache Datencontainer, während Klassen für Objekte verwendet werden, die auf die Daten einwirken müssen und nicht nur daran festhalten.
Sie sind so ziemlich dasselbe. Dank der Magie von C ++ kann eine Struktur Funktionen enthalten, Vererbung verwenden, mit "neu" erstellt werden usw. wie eine Klasse
Der einzige funktionale Unterschied besteht darin, dass eine Klasse mit privaten Zugriffsrechten beginnt, während eine Struktur mit öffentlichen beginnt. Dies ist die Aufrechterhaltung der Abwärtskompatibilität mit C.
In der Praxis habe ich immer Strukturen als Datenhalter und Klassen als Objekte verwendet.
Wie andere darauf hingewiesen haben
Es gibt eine klare Empfehlung, wann welche von Stroustrup / Sutter verwendet werden soll:
Beachten Sie jedoch, dass es nicht ratsam ist, etw. Weiterzuleiten. als Klasse ( class X;
) und definieren Sie es als struct ( struct X { ... }
). Es kann auf einigen Linkern (z. B. g ++) funktionieren und auf anderen (z. B. MSVC) fehlschlagen, sodass Sie sich in der Entwicklerhölle befinden.
class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }
nicht nur mit MSVC 2017 kompiliert und ausgeführt, es erzeugt sogar eine eindeutige Warnung, die Foo
als deklariert, struct
aber als definiert wurde class
. Aber ich erinnere mich auch deutlich daran, dass es unser Team einen halben Tag gekostet hat, diesen dummen Fehler zu finden. Ich bin mir nicht sicher, welche MSVC-Version wir damals verwendet haben.
class
oder nicht struct
, und die beiden sind gemäß dem Standard frei austauschbar (obwohl bekannt ist, dass VS warnt; ich habe immer angenommen, dass dies nur dazu dient, offensichtliche Programmiererfehler zu vermeiden). Hier riecht etwas nicht. Sind Sie sicher, dass es sich nicht um einen ODR-Verstoß handelt?
struct
-vorwärts- class
vorwärts- ersetzt hatte, verschwanden die Probleme. Ab heute finde ich es auch seltsam. Ich würde mich freuen, wenn Sie etwas Licht ins Dunkel bringen könnten.
Klassenmitglieder sind standardmäßig privat.
class test_one {
int main_one();
};
Ist äquivalent zu
class test_one {
private:
int main_one();
};
Also, wenn Sie es versuchen
int two = one.main_one();
Wir werden eine Fehlermeldung erhalten: main_one is private
weil es nicht zugänglich ist. Wir können es lösen, indem wir es initialisieren, indem wir es als öffentlich angeben, dh
class test_one {
public:
int main_one();
};
Eine Struktur ist eine Klasse, in der Mitglieder standardmäßig öffentlich sind.
struct test_one {
int main_one;
};
Mittel main_one
ist privat dh
class test_one {
public:
int main_one;
};
Ich verwende Strukturen für Datenstrukturen, in denen die Mitglieder einen beliebigen Wert annehmen können. Auf diese Weise ist es einfacher.
Ein Vorteil von struct
over class
ist, dass eine Codezeile gespeichert wird, wenn "zuerst öffentliche Mitglieder, dann private" verwendet werden. In diesem Licht finde ich das Schlüsselwort class
nutzlos.
Hier ist ein weiterer Grund, nur struct
und nie zu verwenden class
. Einige Richtlinien für den Codestil für C ++ schlagen vor, kleine Buchstaben für Funktionsmakros zu verwenden. Der Grund dafür ist, dass der Name bei der Konvertierung des Makros in eine Inline-Funktion nicht geändert werden muss. Hier gilt das gleiche. Sie haben Ihre schöne Struktur im C-Stil und eines Tages müssen Sie einen Konstruktor oder eine bequeme Methode hinzufügen. Ändern Sie es in ein class
? Überall?
Die Unterscheidung zwischen struct
s und class
es ist einfach zu mühsam, um das zu tun, was wir tun sollten - das Programmieren. Wie so viele Probleme von C ++ entsteht es aus dem starken Wunsch nach Abwärtskompatibilität.
class
? Haben Sie gedacht, dass eine mit dem struct
Schlüsselwort definierte Klasse keine Elementfunktionen oder keinen Konstruktor haben kann?
joe()
muss mit einem class
Schlüsselwort definiert werden . Jede Klasse mit mindestens 4 int
Mitgliedern muss mit einem struct
Schlüsselwort definiert werden ?
struct
, Aggregate mit Methoden sind definiert mit class
". Zu viel Aufwand.
Sie sind dasselbe mit unterschiedlichen Standardeinstellungen (standardmäßig privat für class
und öffentlich für standardmäßig struct
), sodass sie theoretisch vollständig austauschbar sind.
Wenn ich also nur einige Informationen packen möchte, um mich zu bewegen, verwende ich eine Struktur, auch wenn ich dort einige Methoden (aber nicht viele) eingefügt habe. Wenn es eine größtenteils undurchsichtige Sache ist, bei der die Hauptverwendung über Methoden und nicht direkt für die Datenelemente erfolgt, verwende ich eine vollständige Klasse.
Strukturen haben standardmäßig öffentlichen Zugriff und Klassen haben standardmäßig privaten Zugriff.
Persönlich verwende ich Strukturen für Datenübertragungsobjekte oder als Wertobjekte. Bei Verwendung als solche deklariere ich alle Mitglieder als const, um Änderungen durch anderen Code zu verhindern.
Beide struct
und class
sind unter der Haube gleich, obwohl die struct
Standardeinstellungen für die Sichtbarkeit unterschiedlich sind. Die Standardeinstellung ist öffentlich und die class
Standardeinstellung ist privat. Sie können bei entsprechender Verwendung von private
und eines der beiden ändern, um das andere zu sein public
. Beide erlauben Vererbung, Methoden, Konstruktoren, Destruktoren und alle anderen Extras einer objektorientierten Sprache.
Ein großer Unterschied zwischen den beiden besteht jedoch darin, dass struct
ein Schlüsselwort in C unterstützt wird, während dies class
nicht der Fall ist. Dies bedeutet , dass man ein verwenden können struct
in einer Include - Datei , die sein kann #include
entweder in C ++ oder C, solange das struct
ist eine einfache C - Stil struct
und alles andere in der Include - Datei mit C kompatibel ist, dh keine C ++ bestimmte Schlüsselwörter wie private
, public
, nein Methoden, keine Vererbung usw. usw. usw.
Der AC-Stil struct
kann mit anderen Schnittstellen verwendet werden, die die Verwendung des C-Stils unterstützen struct
, um Daten über die Schnittstelle hin und her zu übertragen.
Der AC-Stil struct
ist eine Art Vorlage (keine C ++ - Vorlage, sondern ein Muster oder eine Schablone), die das Layout eines Speicherbereichs beschreibt. Im Laufe der Jahre wurden Schnittstellen erstellt, die von C und mit C-Plug-Ins verwendet werden können (hier sehen Sie Java, Python und Visual Basic), von denen einige im C-Stil funktionieren struct
.
Technisch sind beide in C ++ gleich - zum Beispiel kann eine Struktur überladene Operatoren usw. haben.
Jedoch :
Ich verwende Strukturen, wenn ich Informationen mehrerer Typen gleichzeitig übergeben möchte. Ich verwende Klassen, wenn ich mich mit einem "funktionalen" Objekt befasse.
Ich hoffe es hilft.
#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;
};
Zum Beispiel gebe ich hier einen Strukturstudenten in den Methoden get ... () zurück - viel Spaß.
Wann würden Sie struct und wann class in C ++ verwenden?
Ich benutze, struct
wenn ich functors
und definiere POD
. Ansonsten benutze ich 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; }
};
std::binary_function<>
ist nicht nur veraltet, c ++ 17 entfernt sie sogar.
Alle Klassenmitglieder sind standardmäßig privat und alle Strukturmitglieder sind standardmäßig öffentlich. Klasse hat standardmäßige private Basen und Struct hat standardmäßige öffentliche Basen. Struktur im Fall von C kann keine Elementfunktionen haben, während wie im Fall von C ++ Elementfunktionen zur Struktur hinzugefügt werden können. Abgesehen von diesen Unterschieden finde ich nichts Überraschendes an ihnen.
Ich verwende struct nur, wenn ich einige Daten ohne zugehörige Elementfunktionen speichern muss (um die Elementdaten zu bearbeiten) und direkt auf die Datenvariablen zugreifen kann.
Beispiel: Lesen / Schreiben von Daten aus Dateien und Socket-Streams usw. Übergeben von Funktionsargumenten in einer Struktur, in der die Funktionsargumente zu viele sind und die Funktionssyntax zu lang erscheint.
Technisch gesehen gibt es keinen großen Unterschied zwischen Klasse und Struktur, außer der Standardzugänglichkeit. Darüber hinaus hängt es vom Programmierstil ab, wie Sie es verwenden.
Ich dachte, dass Structs als Datenstruktur (wie ein Array von Informationen mit mehreren Datentypen) gedacht war und Klassen für Code Packaging (wie Sammlungen von Unterroutinen und Funktionen) vorgesehen waren.
:(
Ich benutze niemals "struct" in C ++.
Ich kann mir nie ein Szenario vorstellen, in dem Sie eine Struktur verwenden würden, wenn Sie private Mitglieder möchten, es sei denn, Sie versuchen absichtlich, verwirrend zu sein.
Es scheint, dass die Verwendung von Strukturen eher ein syntaktischer Hinweis darauf ist, wie die Daten verwendet werden, aber ich möchte lieber nur eine Klasse erstellen und versuchen, dies im Namen der Klasse oder durch Kommentare explizit zu machen.
Z.B
class PublicInputData {
//data members
};
struct
ziemlich explizit zu deklarieren, dass die Mitglieder der Klasse standardmäßig öffentlich sind?