Nichtstatische Dateneinträge in C++ (Nichtstatische Dateneinträge in C++), Lektion, Seite 723181
https://www.purl.org/stefan_ram/pub/nichtstatische_dateneintraege_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Nicht-statische Dateneinträge in C++ 

Nicht-statische Felder

Eine Klasse kann ein nicht-statischen Feld  enthalten.

Solch ein nicht-statisches Feld legt fest, daß ein Objekt mit dem angegebenen Typ und Namen sich dann in jedem Objekt  der Klasse befinden muß. Wenn es beispielsweise drei Objekte einer Klasse mit einem nicht-statischen Felde gibt, hat jedes Objekt eine eigene Inkarnation jenes Feldes – es gibt dann also insgesamt drei verschiedene  Felder. Umgekehrt gibt es ein nicht-statisches Feld einer Klasse gar nicht, solange noch kein Objekt dieser Klasse angelegt wurde.

Wenn keine Mißverständnisse möglich sind, nennt man ein nicht-statisches Feld auch einfach nur ein Feld. Ein Feld wird manchmal auch als ein Unterobjekt  oder als ein Dateneintrag  bezeichnet. Eine Feld eines Objektes O ist ein in jenem Objekt enthaltenes Objekt.

Klasse und Objekte

Klasse
. - - - - - - - - .
: Feld :
: . - - - - - - . :
: : : :
: '- - - - - - -' :
'- - - - - - - - -'

Objekt 0 Objekt 1 Objekt 2
.-----------------. .-----------------. .-----------------.
| Feld | | Feld | | Feld |
| .-------------. | | .-------------. | | .-------------. |
| | | | | | | | | | | |
| '-------------' | | '-------------' | | '-------------' |
'-----------------' '-----------------' '-----------------'

Die Festlegung der nicht-statischen Felder einer Klasse erfolgt dadurch, daß diese – ähnlich wie bei einer Variablendeklaration – im Rumpfe der Klasse (also innerhalb der geschweiften Klammern des Klassenspezifizierers) deklariert werden.

Ein Beispiel

Die Klasse »entity« beschreibt Objekte, die ein Feld namens »entity« enthalten.

Die Festlegung, daß in jedem entity-Objekt ein Unterobjekt »entity« vom Typ »::std::string« enthalten sein soll, erfolgt durch die Deklaration »::std::string entity;« im Klassenrumpf. Diese Deklaration erinnert an eine Variablendeklaration. Sie legt den Typ »::std::string« als Typ  des Feldes und den Bezeichner »entity« als Namen  des Feldes fest.

main.cpp

#include <iostream>
#include <ostream>
#include <string>

struct entity { ::std::string entity; };

int main()
{ entity entity; }

Im obigen Programm enthält die Variable »entity« vom Typ »entity« ein Feld namens »entity« mit dem Wert »""«.

Objekt und Unterobjekt zum Zeitpunkt nach ihrer Erzeugung in symbolischer Darstellung (kein UML)
.--------------------------------.
| entity entity; |
| .----------------------------. |
| | ::std::string entity = ""; | |
| '----------------------------' |
'--------------------------------'

Syntax

Bei der Deklaration »::std::string entity;« in dem obigen Programm handelt es sich um die Deklaration eines Feldes einer Klasse. Dafür gilt die Synax nach C++  2015 9.2. In »::std::string entity;« ist »::std::string« ein »decl-specifier« (genauer: »type-specifier«) und »entity« eine »member-declarator-list«.

C++ 2015 9.2 (vereinfacht)

member-declaration

   .---------------------------------.   .---------------------------------.
| .----------------. V | .------------------------. V .-.
---'---.--->| decl-specifier |---.---'---'--->| member-declarator-list |---'--->( ; )--->
^ '----------------' | '------------------------' '-'
'-------------------------'
C++ 2015 7.1 (vereinfacht)
decl-specifier
.-------------------------.
---.--->| storage-class-specifier |---.--->
| '-------------------------' |
| .-------------------------. |
'--->| type-specifier |---'
'-------------------------'
C++ 2015 7.1.1 (vereinfacht)
storage-class-specifier
.------.
--->( static )--->
'------'

Wir geben hier die Syntax von »type-specifier« und »member-declarator-list« nicht näher an, aber bei den einfachen Deklarationen der hier vorgestellten Art kann man sich unter »type-specifier« einen Typ und unter »member-declarator-list« einen Namen vorstellen.

Nicht-statische Felder

In einer Klasse können auch statische Felder  deklariert werden, die allerdings hier nicht näher behandelt werden sollen.

Um ein statisches Feld zu deklarieren, muß dieses mit dem Speicherklassenspezifizierer »static« deklariert werden.

Da wir diesen Speicherklassenspezifizierer »static« hier nicht  verwenden, nennen wir unsere Felder auch „nicht-statisch “.

Initialisierung

„Fehlinitialisieren“ bezeichnet die Art des Initialisierens, die verwendet wird, wenn kein Initialisierer angegeben wurde.

In dem obigen Programm wird die lokale Variable fehlinitialisiert, da kein Initialisierer angegeben ist.

Im Falle der deklarierten Klasse »entity« werden bei einer Fehlinitialisierung des gesamten Objektes auch alle Felder fehlinitialisiert.

Dies bedeutet bei einem Felde der Klasse »::std::string«, daß es den leeren String »""« (mit der Länge 0) als Wert erhält.

Initialisierung *

Dieser Abschnitt enthält eine Herleitung der eben beschriebene Initialisierung mit Quellenangaben für die einzelnen Schritte.

Wir sehen oben eine eine Nicht-Initialisierung für die lokale Variable »entity«, weil es in der Definition der lokalen Variablen »entity« keinen  Initialisierer gibt.

Bei einem Exemplar einer Klasse bedeutet dies, daß das Exemplar fehlinitialisiert  wird.

If no initializer is specified for an object, the object is default-initialized. ”, 2015 8.5p12

Der Konstruktor der Klasse wird dann mit einer leeren Argumentliste  aufgerufen. Wir haben für die Klasse »entity« keinen Konstruktor definiert. Es wurde jedoch von C++  automatisch ein Konstruktor eingerichtet. Dieser wird nun mit einer leeren Argumentliste aufgerufen.

The constructor thus selected is called, with an empty argument list, to initialize the object. ”, 2015 9.5p7

Bei der Ausführung dieses Konstruktors werden die Felder ohne Initialisierer dann wiederum ihrerseits fehlinitialisiert.

In a non-delegating constructor ” (9) “otherwise, the entity is default-initialized (8.5); ”, 2015 12.6.2p9.3

Das Feld wird also fehlinitialisiert. Nach 8.5p7.1 wird der beste Konstruktor der Klasse »::std::string« für den Initialisierer »()« aufgerufen.

Dokumentation der Klasse »::std::string« nach C++ 2015, 21.4.2 (vereinfacht)
::std::string …();
Anlegen eines leeren ::std::string-Exemplars

Es wird also ein leeres ::std::string-Objekt erzeugt.

Wäre der Typ des Feldes jedoch ein fundamentaler Typ, wie beispielsweise »int«, so würde das Feld nicht  initialisiert werden, da die Fehlinitialisierung eines fundamentalen Objekts die Nichtinitialisierung ist.

Übungsaufgaben

/   Refaktor „Ändern des Namens“

In dem folgenden Programm wird der Bezeichner »entity« sowohl für eine Klasse als auch für ein Objekt (eine lokale Variable eines Blocks) und für ein Feld verwendet. Überarbeiten Sie das Programm, indem Sie dafür sorgen, daß die Klasse den Namen »k«, das Feld den Namen »f« und das Objekt den Namen »o« hat, aber ändern Sie sonst nichts anderes.

main.cpp

#include <iostream>
#include <ostream>
#include <string>

struct entity { ::std::string entity; };

int main() { entity entity; }

/   Definieren einer neuen Klasse

Definieren Sie eine Klasse »integer«, die ein Feld namens »value« vom Typ »int« enthält, legen Sie dann ein Exemplar dieser Klasse mit dem Namen »one« an und verwenden Sie den sizeof-Operator, um die Größe jenes Exemplars »one« auszugeben.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723181 stefan_ram:723181 Nichtstatische Dateneinträge in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723181, slrprddef723181, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/nichtstatische_dateneintraege_c++