Zugriffe auf Felder in C++ (Zugriffe auf Felder in C++), Lektion, Seite 723251
https://www.purl.org/stefan_ram/pub/schreibzugriffe_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Zugriffe auf Felder in C++ 

Zum Lesen  des Wertes eines Feldes wird Name des Feldes wie eine Variable verwendet, wobei ihm der Namen des enthaltenden Objektes mit einem Punkte ».« getrennt vorangestellt wird.

Wie eine lokale Variable, so kann ein Feld auch auf der linken  Seite einer Zuweisung verwendet werden, um einen Wert in das Feld zu schreiben.

main.cpp

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

using namespace ::std::literals;

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

int main()
{ ::entity entity;

/* Wir wollen etwas aus dem Felde lesen und ausgeben: */
::std::cout << '"' << entity.string << '"' << '\n'; /* <-- Leseoperation */

/* Wir wollen etwas in das Feld hineinschreiben: */
entity.string = "alpha"s; /* <-- Schreiboperation */

/* Wir geben dasselbe Feld erneut aus: */
::std::cout << '"' << entity.string << '"' << '\n'; }

::std::cout
""
"alpha"

Vollständige Qualifikation des Feldnamens

Das folgende Programmbeispiel zeigt die in C++  mögliche, aber selten nötige, vollständige Qualifikation eines Feldnamens.

Anstelle der Angabe ».string« kann auch die Angabe ».::entity::string« verwendet werden, bei welcher der Name der Klasse dem Namen des Feldes noch vorangestellt wird. Dies ist aber in der Regel nicht nötig.

main.cpp

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

using namespace ::std::literals;

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

int main()
{

{ ::entity object;
::std::cout << '"' << object.string << '"' << '\n';
object.string = "alpha"s;
::std::cout << '"' << object.string << '"' << '\n'; }

{ ::entity object;
::std::cout << '"' << object.::entity::string << '"' << '\n';
object.::entity::string = "alpha"s;
::std::cout << '"' << object.::entity::string << '"' << '\n'; }}

transcript
""
"alpha"
""
"alpha"

Konstante Objekte

Die Felder eines konstanten Objekts  können in der Regel nicht verändert werden.

main.cpp

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

using namespace ::std::literals;

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

int main()
{ ::entity const object;
::std::cout << '"' << object.string << '"' << '\n';

/* object.string = "alpha"s; */ /* <-- nicht erlaubt */ }

Mehrere Klassen

In einem Programm können auch mehrere verschiedene  Klassen definiert werden.

In dem folgenden Programm definieren wir zwei  Klassen: eine Klasse »::entity« und eine Klasse »::container«.

Ein Objekt der Klasse »::container« („Behälter“) kann ein Objekt der Klasse »::entity« enthalten.

In der main-Funktion wird die Zeichenfolge »abc« in das Objekt »entity« kopieren, und dann wird das Objekt »entity« in das Objekt »container« kopiert.

main.cpp

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

using namespace ::std::literals;

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

struct container { ::entity entity; };

int main()
{ ::entity entity;
::container container;

entity.string = "abc"s; /* <-- erstes Kopieren */
container.entity = entity; /* <-- zweites Kopieren */

::std::cout << container.entity.string << '\n'; }

transcript
abc
Kopieren in Felder
  container
.-----------------------.
| entity | entity
| .-------------------. | 2. .-------------------.
| | string |<------------| string |
| | .---------------. | | Kopie | .---------------. | 1.
| | | abc | | | | | abc |<------------ abc
| | '---------------' | | | '---------------' | Kopie
| '-------------------' | '-------------------'
'-----------------------'

Anwendungsbeispiel

Wir wollen 40 Stück à 4,29 Währungseinheiten kaufen.

main.cpp

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

void kaufen( int stueck, int preis )
{ ::std::cout << "Kaufe " << stueck << " a " << preis << "!\n"; }

int main()
{ int preis { 429 };
int stueck { 40 };
kaufen( preis, stueck ); }

Protokoll
Kaufe 429 a 40!

Vermeidung von Fehlern durch Typisierung.

main.cpp

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

struct stueck { int n; };

struct preis { int n; };

void kaufen( stueck s, preis p )
{ ::std::cout << "Kaufe " << s.n << " a " << p.n << "!\n"; }

int main()
{ preis p{ 429 };
stueck s{ 40 };
kaufen( p, s ); }

Protokoll
main.cpp: In function 'int main()':
main.cpp:15:11: error: could not convert 'p' from 'preis' to 'stueck'
main.cpp

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

struct stueck { int n; };

struct preis { int n; };

void kaufen( stueck s, preis p )
{ ::std::cout << "Kaufe " << s.n << " a " << p.n << "!\n"; }

int main()
{ preis p{ 429 };
stueck s{ 40 };
kaufen( s, p ); }

Protokoll
Kaufe 40 a 429!

»using« schafft hingegen keine neuen Typen, sondern nur andere Namen für bestehende Typen.

main.cpp

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

using stueck = int;

using preis = int;

void kaufen( stueck s, preis p )
{ ::std::cout << "Kaufe " << s << " a " << p << "!\n"; }

int main()
{ preis p{ 429 };
stueck s{ 40 };
kaufen( p, s ); }

Protokoll
Kaufe 429 a 40!

Übungsfragen

?   Mehrere Klassen

In dem folgenden Programm wurde die Reihenfolge der beiden Zuweisungen an Felder von zwei Objekten im Vergleich zu einem weiter oben stehendem Programm vertauscht. Das obenstehende Programm gab »abc« aus. Warum gibt das folgende Programm nun nicht mehr »abc« aus?

main.cpp

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

using namespace ::std::literals;

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

struct container { ::entity entity; };

int main()
{ ::entity entity;
::container container;
container.entity = entity;
entity.string = "abc";
::std::cout << container.entity.string << '\n'; }

Übungsaufgaben

/   Feldzugriffe

Legen Sie eine Klasse »object« mit einem double-Feld namens »weight« an und definieren Sie dann ein Objekt »o« jener Klasse. Schreiben Sie den Wert »1.5« in das Feld »weight« jenes Objektes und geben sie danach den Wert jenes Feldes jenes Objektes aus.

/   Direkteres Schreiben

In einem weiter oben stehenden Beispielprogramm wurde die Zeichenfolge »abc« in das Objekt »entity« kopiert, und dann wurde das Objekt »entity« in das Objekt »container« kopiert.

Wir hätten aber die Zeichenfolge »abc« auch gleich in das entity-Objekt kopieren können, welches sich im container-Objekt befindet, und dadurch auf die zweite Kopie verzeichen können. Fügen Sie eine Anweisung dafür an Stelle des Kommentars in das folgende Programm ein. Das Programm sollte dann wieder »abc« ausgeben.

main.cpp

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

using namespace ::std::literals;

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

struct container { ::entity entity; };

int main()
{ ::container container;

/* hier die Zeichenfolge in das vorhandene entity-Objekt schreiben */

::std::cout << container.entity.string << '\n'; }

Notiz zu gleichen Namen *

In C++ 2015 heißt es zwar:

»[I]f T has a user-declared constructor (12.1), every non-static data member of class T shall have a name different from T.«, C++ 2015, 9.2.15,

aber dies sollte es nicht verbieten, ein Feld wie eine Klasse zu nennen, falls es keinen benutzerdeklarierten Konstruktor gibt.

Dennoch meldet ein Compiler einen Fehler, falls der Name des Feldes dann mit vollständiger Qualifikation verwendet wird, weil er darin nun den Namen eines Konstruktors sieht.

main.cpp

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

using namespace ::std::literals;

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

int main()
{ ::entity entity{ "abc"s };
::std::cout << entity.::entity::entity /* <- Fehlermeldung */ << '\n';
::std::cout << entity.text << '\n'; }

Konsole
In function 'int main()':
error: cannot call constructor 'entity::entity' directly
::std::cout << entity.::entity::entity << '\n';
^

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 stefanram723251 stefan_ram:723251 Zugriffe auf Felder in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723251, slrprddef723251, 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/schreibzugriffe_c++