C++-Typsystem modernes (C++)
Das Konzept des Typs ist in C++ sehr wichtig.Jede Variable, Funktionsargument und den Rückgabewert muss einen Typ verfügen kompiliert.Außerdem jeder Ausdruck (einschließlich Literalwerte) wird implizit einen Typ durch den Compiler angegeben, bevor er ausgewertet wird.Einige Beispiele für Typen enthalten int, um ganzzahlige Werte, double zu speichern, um Gleitkommawerte (auch als skalare Datentypen) oder die Standardbibliotheksklasse Std::basic_string zu speichern, um Text zu speichern.Sie können auch einen eigenen Typ erstellen, indem Sie class oder struct definieren.Der Typ gibt Speicher, der für die Variable zugeordnet ist (oder Ausdrucksergebnis), die Arten von Werten an, die in dieser Variablen gespeichert werden, wie diese Werte (als Bitmuster) interpretiert werden, und in den Vorgängen, die darauf ausgeführt werden können.Dieser Artikel enthält eine informelle Übersicht der Hauptfunktionen des C++-Typsystems.
Terminologie
Variable: Der symbolische Namen einer Datenmenge, damit der Name verwendet werden kann, um auf die Daten zuzugreifen, wird es überall in dem Bereich des Codes an, in der er definiert wird.In C++ "Variable" wird im Allgemeinen verwendet, um Instanzen von skalaren Datentypen verweist, während Instanzen anderer Typen normalerweise "Objekte" aufgerufen werden.
- Objekt: Der Einfachheit halber und Konsistenz, verwendet dieser Artikel den Begriff "Objekt", jede Instanz einer Klasse oder Struktur zuzugreifen und wenn dieser häufig verwendet wird, umfasst alle Typen, sogar skalare Variablen.
POD-Typ (Plain Old Data): Diese informelle Kategorie von Datentypen in C++ verweist auf Typen an, die (siehe den grundlegenden Typabschnitt) skalar sind oder HÜLSENklassen sind.Eine HÜLSENklasse hat keine statischer Datenmember, die nicht auch Hülsen sind, und hat keine benutzerdefinierten benutzerdefinierten Konstruktoren, Destruktoren oder benutzerdefinierten Zuweisungsoperatoren.Darüber hinaus kann eine HÜLSENklasse hat keine virtuellen Funktionen, keine Basisklasse und die nicht private oder geschützte nicht statischen Datenmembern.HÜLSENtypen sind für Austausch der externen Daten, beispielsweise mit einem Modul häufig verwendet, das in die Programmiersprache C geschrieben wird (das nur HÜLSENtypen ist).
Angeben von Variablen und Funktionstypen
C++ ist eine stark typisierte Sprache und wird auch statisch-eingegeben; Jedes - Objekt verfügt über einen Typ und dieser Typ nie ändert (nicht mit Objekten der statischen Daten verwechselt werden).
Wenn Sie eine Variable deklarieren im Code, müssen Sie entweder den Typ explizit angeben, oder Sie verwenden das auto-Schlüsselwort, um den Compiler anzuweisen, um den Typ aus dem Initialisierer abzuleiten.
Wenn Sie eine Funktion deklarieren im Code, müssen Sie den Typ jedes Arguments und ihres Rückgabewerts oder void angeben, wenn kein Wert von der Funktion zurückgegeben wird.Die Ausnahme ist, wenn Sie Funktionsvorlagen verwenden, die Argumente von beliebigen Typen ermöglichen.
Nachdem Sie zuerst eine Variable deklarieren, können Sie den Typ nicht zu einem späteren Zeitpunkt ändern.Sie können jedoch den Rückgabewert des Werts der Variablen oder einer Funktion in eine andere Variable eines anderen Typs kopieren.Solche Vorgänge werden manchmal Typkonvertierungen aufgerufen, die erforderlich sind, jedoch sind auch mögliche Quellen von Datenverlust oder der Unrichtigkeit.
Wenn Sie eine Variable des HÜLSENtyps deklarieren, empfehlen wir dringend initialisieren, die sie bedeutet, ihm einen Anfangswert zu geben.Wenn Sie eine Variable initialisieren, hat sie einen "Garbage" Wert, der besteht aus, was Bits aufgetretenen, um in dieser Speicherort zu zuvor sein.Dies ist ein wichtiger Aspekt von C++, um sich zu erinnern, insbesondere wenn Sie in einer anderen Sprache stammen, die Initialisierung für Sie bearbeitet.Wenn eine Variable des NichtHÜLSENklassentyps deklariert, behandelt der Konstruktor Initialisierung.
Im folgenden Beispiel werden einige einfache Variablendeklarationen mit einigen Beschreibungen für jedes an.Das Beispiel zeigt auch, wie der Compiler Typinformationen verwendet, um bestimmte folgende Vorgänge in der Variablen zu gewähren oder verweigern.
int result = 0; // Declare and initialize an integer.
double coefficient = 10.8; // Declare and initialize a floating
// point value.
auto name = "Lady G."; // Declare a variable and let compiler
// deduce the type.
auto address; // error. Compiler cannot deduce a type
// without an intializing value.
age = 12; // error. Variable declaration must
// specify a type or use auto!
result = "Kenny G."; // error. Can’t assign text to an int.
string result = "zero"; // error. Can’t redefine a variable with
// new type.
int maxValue; // Not recommended! maxValue contains
// garbage bits until it is initialized.
Grundlegende (Einbauten) Typen
Im Gegensatz zu einigen Sprachen C++ hat keinen universellen Basistyp, von dem alle anderen Typen abgeleitet werden.Die Visual C++ Implementierung der Sprache umfasst viele grundlegenden Typen, auch als integrierten Datentypen.Dies schließt numerische Typen wie int, double, long, bool, plus die char und wchar_t-Typen für ASCII- und UNICODE-Zeichen, bzw. ein.Grundlegendste Typen (außer bool, double, wchar_t und verwandten Typen) haben alle Versionen ohne Vorzeichen, die den Wertebereich ändern, den die Variable speichern kann.Beispielsweise kann int, die eine 32-Bit-Ganzzahl mit Vorzeichen, speichert einen Wert von -2.147.483.648 bis 2.147.483.647 darstellen.unsigned int, das auch als 32-Bit-/x86-Prozess gespeichert wird, kann einen Wert von 0 bis 4.294.967.295 speichern.Die Gesamtzahl der möglichen Werten in jedem Fall entspricht; nur der Bereich ist anders.
Die grundlegenden Typen werden vom Compiler erkannt, der eingebaute Regeln verfügt, die bestimmen, welche Vorgänge Sie auf sie ausgeführt werden können und wie sie zu anderen grundlegenden Typen konvertiert werden können.Eine vollständige Liste der integrierten Datentypen und ihrer Größe und numerischengrenzen, finden Sie unter Grundlagen-Typen (C++).
Die folgende Abbildung zeigt die relative Größe der integrierten Datentypen an:
In der folgenden Tabelle werden die am häufigsten verwendeten grundlegenden Typen auf:
Typ |
Größe |
Kommentar |
---|---|---|
int |
4 Bytes |
Die Standardauswahl für ganzzahlige Werte. |
double |
8 Bytes |
Die Standardauswahl für Gleitkommawerte. |
bool |
1 Byte |
Stellt Werte dar, die entweder true oder false sein können. |
char |
1 Byte |
Verwenden Sie für ASCII-Zeichen in älteren Zeichenfolgen in C-Format oder in std::string Objekten, die nie auf den UNICODE konvertiert werden müssen. |
wchar_t |
2 Bytes |
Stellt "breite" Zeichenwerte dar, die sich im UNICODE-Format codiert werden (UTF-16 möglicherweise auf Windows, andere Betriebssysteme abweichen).Dies ist der Schrifttyp, der in Zeichenfolgen des Typs std::wstring verwendet wird. |
unsigned char |
1 Byte |
C++ hat keine integrierten byte-Typ.Verwenden Sie char ohne Vorzeichen, um einen Bytewert darzustellen. |
unsigned int |
4 Bytes |
Nehmen Sie Auswahl für Bitflags den Standardwert an. |
long long |
8 Bytes |
Stellt sehr große ganzzahlige Werte dar. |
Der ungültige Typ
Der void-Typ ist ein besonderer Typ; Sie können eine Variable des Typs void nicht deklarieren, aber Sie können eine Variable des Typs void * (Zeiger auf void) deklarieren, der manchmal ist erforderlich, wenn von unformatierten (nicht typisierten) Arbeitsspeicher belegt.Zeiger auf void sind jedoch nicht typsicher und im Allgemeinen ist ihre Verwendung stark in modernem C++ aufrufen.In einer Funktionsdeklaration ein void Rückgabewert bedeutet, dass die Funktion keinen Wert zurückgibt, Dies ist ein Common und eine zulässige Verwendung von void.Während die Programmiersprache C Funktionen erforderlich, die die nullparameter verfügen, der von void in der Parameterliste beispielsweise fou(void) zu deklarieren, wird hierdurch in modernem C++ verfahren und sollte deklariert werden fou().Weitere Informationen finden Sie unter Typkonvertierungen und Typsicherheit modernes (C++).
const Typqualifizierer
Alle integrierten oder benutzerdefinierten Typ werden durch das const Schlüsselwort qualifiziert werden.Darüber hinaus sind möglicherweise Memberfunktionen const- qualifiziert und sogar const- überladen.Der Wert eines const-Typs kann nicht geändert werden, nachdem er initialisiert ist.
const double PI = 3.1415;
PI = .75 //Error. Cannot modify const variable.
Der const Qualifizierer wird für zahlreiche in der Funktion verwendet und Variablendeklarationen und "const Korrektheit" ist ein wichtiges Konzept in C++; im Wesentlichen bedeutet, const zu verwenden, um sicherzustellen dass Werte zur Kompilierungszeit nicht versehentlich geändert werden.Weitere Informationen finden Sie unter const-Feld (C++).
Ein const-Typ wurde aus der nicht konstanten Version unterschiedlich; ist z const int ein unterschiedlichen Typ von int.Sie können den Operator C++ const_cast zu diesen seltenen Situationen verwenden, wenn Sie Const-heit einer Variable entfernen müssen.Weitere Informationen finden Sie unter Typkonvertierungen und Typsicherheit modernes (C++).
Zeichenfolgentypen
Genau genommen, hat die Programmiersprache C++ keinen integrierten "Zeichenfolge Typ; char und einzelne Zeichen wchar_t Speichers - Sie müssen ein Array dieser Typen deklarieren, die eine Zeichenfolge anzugleichen und einen endgültige NULL-Zeichen-Wert (beispielsweise, ‘\0’ ASCII) dem Arrayelement hinzufügen eine Vergangenheit das letzte gültige Zeichen (auch aufgerufen "eine Zeichenfolge im C-Format ").Zeichenfolgen in C-Format erforderlichen viel mehr Code geschrieben werden oder die Verwendung von Dienstbibliotheksfunktionen der externen Zeichenfolge.Aber in modernem C++, wird die standardmäßige Bibliothekstypen std::string (für 8-Bit -- e-artig Zeichenfolgen char) oder (für std::wstring 16-Bit- --e-artig Zeichenfolgen wchar_t).Diese STL-Container können für systemeigene Zeichenfolgentypen betrachtet werden, da sie Teil der Standardbibliotheken sind, die in jeder kompatiblen C++-Buildumgebung enthalten sind.Verwenden Sie einfach die #include <string>-Direktiven, um diese Typen bereitzustellen im Programm.(Wenn Sie MFC oder ATL verwenden, ist die CString-Klasse auch verfügbar, aber nicht Teil des C++-Standards.) Die Verwendung von auf NULL endende Zeichenarrays (die Zeichenfolgen in C-Format bereits erwähnt) wird dringend modernem in C++ aufrufen.Weitere Informationen dazu, wie entscheidet, der Zeichenfolgentyp, um in einem modernen C++-Programm zu verwenden finden und wie zwischen verschiedenen Typen, Zeichenfolgen und Text modernes (C++) konvertiert.
Benutzerdefinierte Typen
Wenn Sie class, struct, union oder enum definieren, das Konstrukt im Rest des Codes verwendet wird, als ob es ein einfacher Typ war.Es hat eine bekannte Größe im Arbeitsspeicher, und bestimmte Regeln zu, wie er verwendet werden kann, gelten für ihn für Kompilierzeitüberprüfung und zur Laufzeit für die Lebensdauer des Programms.Die wichtigsten Unterschiede zwischen den grundlegenden integrierten Datentypen und den benutzerdefinierten Typen sind, wie folgt:
Der Compiler hat kein integriertes Wissen eines benutzerdefinierten Typs.Er "erfährt" Typ, wenn er zuerst die Definition während des Kompilierungsprozesses auftritt.
Sie geben an, welche Vorgänge auf dem Typ ausgeführt werden können und wie er auf andere Typen konvertiert werden kann, indem (durch Überladen) die entsprechenden Operatoren, entweder als Klassenmember oder Funktionen definiert.Weitere Informationen finden Sie unter Überladen.
Sie müssen nicht statisch eingegeben werden (die Regel, die ein Objekttyp nie geändert wird).Durch die Mechanismen der Vererbung und der Polymorphie kann eine Variable möglicherweise, die als benutzerdefinierter Typ Klasse deklarierte (bezeichnet als eine Objektinstanz einer Klasse) einen anderen Typ als zur Laufzeit zur Kompilierungszeit.Weitere Informationen finden Sie unter Abgeleitete Klassen.
Zeigertypen
Zurückgehend hinsichtlich der frühesten Versionen des Programmiersprache C, C++ fährt fort, um Sie eine Variable eines Zeigertyps deklarieren zu lassen, indem Sie den speziellen Deklarator * (Sternchen) verwendet.Ein Zeigertyp speichert die Adresse des Speicherorts im Arbeitsspeicher, in dem der tatsächliche Datenwert gespeichert wird.In modernem C++ wird auf diese als unformatierte Zeiger und werden im Code durch besondere Operatoren * (Sternchen) oder -> (Bindestrich mit groß-als) zugegriffen.Dies wird Dereferenzieren aufgerufen und das hängt das, das Sie verwenden, davon ab, ob Sie einen Zeiger auf einen Skalarwert oder einen Zeiger auf einen Member in einem - Objekt.Das Arbeiten mit Zeigertypen lang ist einer der schwierigsten und verwirrendsten Aspekte von C- und C++-Programmentwicklung erwiesen.In diesem Abschnitt werden einige Fakten und Vorgehensweisen zu helfen, unformatierte Zeiger zu verwenden, wenn Sie möchten, aber in modernem C++ wird es nicht mehr benötigt oder (empfohlen), unformatierte Zeiger für Objektbesitz, aufgrund der Entwicklung intelligenter Zeiger überhaupt zu verwenden (erläutert mehr am Ende dieses Abschnitts).Es ist noch hilfreich und sicher, unformatierte Zeiger für das Beobachten von Objekten zu verwenden, doch, wenn Sie sie für Objektbesitz verwenden müssen, sollten Sie dies mit Vorsicht und sehr reiflicher Überlegung von, wie die Objekte, die davon besitzen, erstellt und zerstört werden.
Der erste Schritt, der Sie wissen sollten, deklariert eine unformatierte Zeigervariable zuordnet nur Speicher, der erforderlich ist, um eine Adresse der Speicheradresse zu speichern, dass der Zeiger verweisen wird, wenn er dereferenziert wird.Speicherplatzbelegung für den Datenwert selbst (auch aufgerufen Sicherungsspeicher) wird noch nicht zugeordnet.Das heißt, indem Sie eine unformatierte Zeigervariable deklarieren, erstellen Sie eine Speicheradressenvariable, keine tatsächliche Datenvariable.Das Dereferenzieren einer Zeigervariable, bevor es, dass sie eine gültige Adresse auf einen Sicherungsspeicher enthält, verursacht nicht definiertes Verhalten (normalerweise ein schwer wiegender Fehler) im Programm sicherstellen.Im folgenden Beispiel wird diese Art von Fehler:
int* pNumber; // Declare a pointer-to-int variable.
*pNumber = 10; // error. Although this may compile, it is
// a serious error. We are dereferencing an
// uninitialized pointer variable with no
// allocated memory to point to.
Das Beispiel dereferenziert Zeigertyps ohne Arbeitsspeicher zuordnen können, um die tatsächlichen Ganzzahldaten oder einen gültigen Speicherort zu speichern, die zugewiesen werden.Der folgende Code korrigiert diese Fehler:
int number = 10; // Declare and initialize a local integer
// variable for data backing store.
int* pNumber = &number; // Declare and initialize a local integer
// pointer variable to a valid memory
// address to that backing store.
...
*pNumber = 41; // Dereference and store a new value in
// the memory pointed to by
// pNumber, the integer variable called
// “number”. Note “number” was changed, not
// “pNumber”.
Der korrigierte lokale Stapelarbeitsspeicher der Codebeispiel wird mithilfe von, um des Sicherungsspeichers zu erstellen, dass pNumber auf zeigt.Wir verwenden einen einfachen Typ der Einfachheit halber.In der Praxis werden der Sicherungsspeicher für Zeiger am häufigsten benutzerdefinierte Typen, die dynamisch-zugeordnet werden in einem Bereich des Arbeitsspeichers aufgerufen den Heap (oder "freien Speicher ") mithilfe eines new-Schlüsselwortausdruck verwendet (Programmierung in der im C-Format, die ältere malloc() wurde C Ablaufbibliotheksfunktion verwendet).Sobald zugeordnet, wird diese "Variablen" normalerweise, als "Objekt", insbesondere wenn sie auf Grundlage einer Klassendefinition sind.Arbeitsspeicher, der mit new zugeordnet ist, muss durch eine entsprechende delete-Anweisung (oder, wenn Sie die malloc()-Funktion, um sie verwendeten zuzuordnen, die C-Laufzeitfunktion dar free()) gelöscht werden.
Es ist jedoch einfach zu vergessen, ein Objekt dynamisch-zugeordnetes besonders komplexen im Code zu löschen, der einen Ressourcenfehler verursacht, der einen Speicherverlust aufgerufen wird.Aus diesem Grund wird die Verwendung von unformatierten Zeigern stark in modernem C++ aufrufen.Es ist fast immer besser, einen unformatierten Zeiger in intelligenter Zeiger zu umschließen, die automatisch den Arbeitsspeicher frei, wenn ihr Destruktor aufgerufen wird (wenn der Code aus dem Bereich für den intelligenten Zeiger erlischt); indem Sie intelligenten Zeiger verwenden, vermeiden Sie praktisch eine ganze Klasse Fehler in den C++-Programmen.Im folgenden Beispiel wird angenommen, dass MyClass ein benutzerdefinierter Typ ist, der eine öffentliche Methode DoSomeWork(); hat
void someFunction() {
unique_ptr<MyClass> pMc(new MyClass);
pMc->DoSomeWork();
}
// No memory leak. Out-of-scope automatically calls the destructor
// for the unique_ptr, freeing the resource.
Weitere Informationen zu intelligenten Zeiger, finden Sie unter Intelligente Zeiger modernes (C++).
Weitere Informationen zu Zeigerkonvertierungen, finden Sie unter Typkonvertierungen und Typsicherheit modernes (C++).
Weitere Informationen über Zeiger im Allgemeinen, finden Sie unter Zeiger.
Windows-Datentypen
In klassischem Win32, das für C und C++ programmiert, verwenden die meisten Funktionen Windows-spezifische Typdefinitionen und #define Makros (definiert in windef.h) die Typen von Parametern und Rückgabewerten anzugeben.Diese "Windows-Datentypen" sind meistens nur die speziellen Namen (Alias) integrierte Datentypen angegeben C/C++.Eine vollständige Liste dieser Typdefinitionen und Präprozessordefinitionen, finden Sie unter Windows Data Types.Einige dieser Typdefinitionen, wie HRESULT und LCID, sind nützlich und beschreibt.Andere, wie INT, haben keine besondere Bedeutung und sind nur Alias für grundlegende C++-Typen.Andere Windows-Datentypen über Namen, die von den Tagen von C-Programmierung und von 16-Bit-Prozessoren beibehalten werden, und haben keinen Zweck oder das Bedeutung auf moderner Hardware oder Betriebssystemen.Es gibt auch die speziellen Datentypen, die mit der Windows Runtime-Bibliothek zugeordnet sind, als aufgeführt Windows Runtime base data types.In modernem C++ ist die allgemeine Richtlinie, die grundlegenden Typen C++ vorzuziehen, es sei denn, der - Typ von Windows zusätzlicher Bedeutung mitteilt darüber, wie der Wert interpretiert werden soll.
Weitere Informationen
Weitere Informationen zum C++-Typsystem, finden Sie unter folgenden Themen.
Beschreibt Werttypen zusammen mit Probleme in Bezug auf ihre Verwendung. |
|
Beschreibt allgemeine Typkonvertierungsprobleme und -shows, wie sie vermieden werden. |