Paare in C++ [] (Paare in C++), Lektion, Seite 721318
https://www.purl.org/stefan_ram/pub/paare_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Verbundobjekte in C++ 

Fundamentale Objekte

Ein fundamentaler Typ  ist einer der fest in der Programmiersprache eingebauten Typen für ganze Zahlen, Gleitkommazahlen und so weiter. Wir geben hier keine vollständige Aufzählung aller fundamentalen Typen an, da es für den Anfang reicht, an die beiden Beispiele »int« und »double« zu denken. (Der Typ »::std::string« und Adreßtypen sind nicht  fundamental.)

Ein fundamentales Objekt  (oder „Fundamentalobjekt “) ist ein Objekt eines fundamentalen Typs.

Das folgende Programm zeigt ein fundamentales Objekt. Es enthält einen einzelnen Wert eines fundamentalen Typs.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>

int main()
{ auto first { 8 }; /* Fundamentalobjekt */
::std::cout << first << '\n'; }

transcript
8

Es sei hier daran erinnert, daß ein Objekt  ein Speicher ist, der einen Wert eines Typs aufnehmen kann. Das Objekt »first« ist beispielsweise der Name eines int-Objektes, also eines Objektes, welches einen Wert des Typs »int« aufnehmen kann.

Eine Variable  ist dann praktisch ein Name  für ein bestimmtes Objekt zusammen mit jenem Objekt, wie beispielsweise »first«. Im Unterschied zur Variablen »first«, die den Namen »first« hat, hat das Objekt aber keinen  Namen. (Es gibt auch Objekte ohne eine zugehörige Variable.)

Verbundobjekte und ihre Unterobjekte

Verbundobjekte traten wohl erstmals in der Programmiersprache COBOL  auf.

Ein Verbundobjekt ist ein Objekt, das eine beliebige (nicht-negative und ganzzahlige) Anzahl (0, 1, 2, …) von Objekten enthält, die auch Einträge, Dateneinträge, Elemente, Datenelemente, Komponenten, Unterobjekte  oder nicht-statische Felder  des Verbundobjekts genannt werden.

Es handelt sich hierbei um Objekte, die als Teile eines anderen Objektes auftreten. Sie müssen nicht alle denselben Typ haben, sondern können unterschiedliche Typen haben.

Wir sprechen hier von einem Verbundobjekt, weil es Verbundobjekt oft mehrere Objekte miteinander zu einem Objekt verbindet  (nämlich zu einem Verbund  [also einer Verbindung ] von Objekten – dem Verbundobjekt).

Es handelt sich bei den Unterobjekten sozusagen um Variablen, die in einer anderen Variablen (dem Verbundobjekt) enthalten sind.

Manchmal vergleicht man ein Objekt auch mit einem Datensatz und bezeichnet die Einträge dann als Felder.

Objekte können also Felder enthalten, in die man schreiben und aus denen man lesen kann.

Ein Verbund kennt für jedes seiner Unterobjekte einen Typ  und einen Namen. Deswegen sagen wir auch, daß die Unterobjekte im Objekt eingetragen  seien und bezeichnen sie als Einträge des Objekts.

Die folgende Abbildung zeigt beispielsweise ein Verbundobjekt.

Verbundobjekt und zwei int-Unterobjekte
  Verbund
.----------------------------.
| .------------------------. |
| | int | |
| '------------------------' |
| .------------------------. |
| | int | |
| '------------------------' |
'----------------------------'

Ein fundamentales Objekt läßt sich hingegen nicht weiter in Unterobjekte zerlegen.

Wie viele Unterobjekt ein Verbundobjekt enthält und welche Typen und Namen diese jeweils haben, wird durch den Typ  des Verbundobjekts festgelegt. Wir werden die dazugehörige Dokumentation  aber erst in einer späteren Lektion behandeln.

Die Erzeugungsfunktion »::std::make_pair«

Die Erzeugungsfunktion »::std::make_pair« ergibt („erzeugt“) ein Verbundobjekt. Es enthält in dem folgenden Programm zwei Unterobjekte vom Typ »int«, welche die Werte »2« beziehungsweise »7« enthalten.

In dem folgenden Programm wird diese Erzeugungsfunktion zur Initialisierung des Objekts »compound« verwendet.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::make_pair */

int main()
{ auto const compound { ::std::make_pair( 2, 7 ) }; }

transcript
(keine Ausgabe)

Das obenstehende Beispielprogramm erzeugt derzeit noch keine  Ausgabe, weil wir noch nicht gelernt haben, wie wir ein Verbundobjekt oder seine Einträge ausgeben.

Die Initialisierung eines Objektes mit einem Anfangswert in der Schreibweise mit geschweiften Klammern und der Aufruf einer Funktion mit zwei Zahlen als Argumenten wurde bereits im Grundkurs behandelt, so daß die Deklaration »auto p { ::std::make_pair( 0, 0 ) };« für uns nichts Neues ist.

Die beiden Argumentwerte  der Erzeugungsfunktion legen die Werte  der beiden Unterobjekte des Verbundobjektes fest. Die Typen  der beiden Komponenten werden durch die Typen der Initialisierungsausdrücke  (beide »int«) festgelegt.

Das Verbundobjekt »compound« aus dem vorangegangenen Programm enthält beispielsweise zwei  Unterobjekte: »first« und »second«.

Verbundobjekt und zwei int-Unterobjekte
    compound
.----------------------------.
| |
| first |
| .------------------------. |
| | int { 2 } | |
| '------------------------' |
| |
| second |
| .------------------------. |
| | int { 7 } | |
| '------------------------' |
'----------------------------'

Die Objekte, die von der Erzeugungsfunktion »::std::make_pair« erzeugt werden, haben alle immer genau zwei Unterobjekte, deren Namen immer »first« und »second« lauten.

Der Eintragspunkt ».«

Der Eintragspunkt ».« trat wohl erstmals in der Programmiersprache PL/I  und kam dann über die Programmiersprache C  nach C++.

Er erlaubt es, einen Eintrag eines Objekts anzugeben, indem der Eintrag hinter einen Ausdruck für ein Verbundobjekt geschrieben wird.

So ist »compound.first« das Unterobjekt mit dem Namen »first« innerhalb des Verbundobjekts »compound«.

»compound.second« ist das Unterobjekt mit dem Namen »second« innerhalb des Verbundobjekts »compound«.

Die beiden Namen »first« und »second« sehen wir als Einträge in »compound« an und bezeichnen den Punkt daher auch als Eintragspunkt.

Das folgende Programm zeigt, daß wird die Werte in den beiden Unterobjekten auf diese Weise nun ausgeben können.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::make_pair */

int main()
{ auto const compound { ::std::make_pair( 8, 4 ) };
::std::cout << compound.first << '\n';
::std::cout << compound.second << '\n'; }

transcript
8
4

Das folgende Programm zeigt, daß die beiden Teilobjekt auch auf der linken Seite des Gleichheitszeichens einer Zuweisung stehen können, nachdem das »const« weggelassen wurde.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::make_pair */

int main()
{ auto compound { ::std::make_pair( 8, 4 ) };
compound.first = 2;
compound.second = 7;
::std::cout << compound.first << '\n';
::std::cout << compound.second << '\n'; }

transcript
2
7

Verbundobjekte in C++ 

Es ist oft relativ einfach, in C++  Verbundobjekte zu verwenden, da die Regeln für ihre Verwendung den uns schon bekannten fundamentalen Objekten, wie int-Objekten, nachempfunden sind. Teilweise ist dies einfacher als in Java, wo Verbundobjekte durch sogenannte „Referenzen“ dargestellt werden, für die andere  Regeln als für die elementaren Datentypen, wie »int«, gelten.

Klassen in C++ 

Der Aufbau von Verbundobjekten wird durch Klassen  festgelegt, für deren Entwurf und Definition man aber etwas mehr lernen muß. Deswegen behandelt dieser Kurs zunächst das einfache und für sich bereits nützliche Thema der Verwendung  von Verbundobjekten bereits vorhandener  Klassen.

Die bei Facebook  am häufigsten verwendete Klasse ist »::std::string« (Quelle: Video: Nicholas Ormrod: “The strange details of std::string at Facebook ”, Cppcon 2016 ). Von dieser Klasse wurde schon im Grundkurs Gebrauch gemacht.

Mehrere unabhängige  Verbundobjekte

Das folgende Programm zeigt das Anlegen zweier  Verbundobjekte. Da jedes dieser beiden Objekte zwei int-Speicher enthält, haben wir insgesamt vier unabhängige int-Speicher zu unserer Verfügung.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::make_pair */

int main()
{ auto p { ::std::make_pair( 0, 0 ) };
auto q { ::std::make_pair( 0, 0 ) };

p.first = 1;
p.second = 2;
q.first = 3;
q.second = 4;

::std::cout << p.first << '\n';
::std::cout << p.second << '\n';
::std::cout << q.first << '\n';
::std::cout << q.second << '\n'; }

transcript
1
2
3
4

Die Dokumentation der Funktion »make_pair«

Die Originaldokumentation der Funktion »make_pair« ist derzeit für uns noch nicht vollkommen verständlich. Statt dessen können bis auf weiteres die folgenden Aussagen zu dieser Funktion als Ersatz verwendet werden:

Zustände

Verschiedene Objekt einer Klasse können sich unterscheiden, beispielsweise können zwei ::std::pair<int,int>-Paare sich in den Werten in ihren Feldern unterscheiden. Das, worin sich verschiedene Objekte einer Klasse unterscheiden können (abgesehen von ihrer Adresse), nennen wir den Zustand  der Objekte. Man kann auch vom Inhalt  oder Wert  eines Objekts sprechen, aber jene Begriffe werden eher bei fundamentalen Objekten verwendet.

Exemplare von Klassen

Objekte einer Klasse nennen wir auch Exemplare  dieser Klasse.

Die Klasse eines Exemplars ist gleichzeitig der Typ  eines Ausdrucks für jenes Exemplars.

Ein Exemplar einer Klasse ist ein Objekt, dessen Eigenschaften einerseits durch seine Klasse und andererseits auch noch durch den Zustand jenes Exemplars festgelegt werden.

Nach der Deklaration »::std::string const a{ "alpha" };« hat der Name (Ausdruck) »a« als Typ die Klasse »::std::string« und als Wert ein Exemplar dieser Klasse, welches die Zeichenfoge »alpha« repräsentiert. Dieses Exemplar wurde bei der Ausführung der Definition »::std::string const a{ "alpha" };« erzeugt.

Übungsfragen

?   Typen von Ausdrücken

Welche beiden Typen  haben die beiden Ausdrücke »p.first« und »p.second« in dem folgenden Programm jeweils?

main.cpp

#include <initializer_list>
#include <iostream>
#include <ostream>
#include <utility> /* ::std::pair */
#include <string>

using namespace ::std::literals;

int main()
{ auto p { ::std::make_pair( "abc"s, 2.0 ) };
::std::cout << p.first << '\n';
::std::cout << p.second << '\n'; }

transcript
abc
2

?   Werte von Ausdrücken

Welche beiden Werte  gibt das folgende Programm aus?

main.cpp

#include <initializer_list>
#include <iostream>
#include <ostream>
#include <utility> /* ::std::pair */
#include <string>

using namespace ::std::literals;

int main()
{ auto p { ::std::make_pair( 1, 1 ) };
auto q { ::std::make_pair( 2, 2 ) };
q.second = 4;
p.first = q.second;
::std::cout << p.first << '\n';
::std::cout << p.second << '\n'; }

Übungsaufgaben

/   Übungsaufgabe

Schreiben Sie eine Anweisung, welche die beiden Teile eines int-Paares miteinander vertauscht!

Das folgende Programm, welches jetzt »5« und »2« (in dieser Reihenfolge) ausgibt, sollte nach Einsetzen der Anweisung an der Stelle des Kommentars dann »2« und »5« (in dieser Reihenfolge) ausgeben.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::pair */

int main()
{ auto p { ::std::make_pair( 5, 2 ) };

/* Hier die Anweisung einsetzen! */

::std::cout << p.first << '\n';
::std::cout << p.second << '\n'; }

transcript
5
2

/   Übungsaufgabe

Schreiben Sie eine Anweisung, welche die Inhalte zweier int-Paare miteinander vertauscht!

Das folgende Programm, welches jetzt »3«, »4«, »1« und »2« (in dieser Reihenfolge) ausgibt, sollte nach Einsetzen der Anweisung dann »1«, »2«, »3« und »4« (in dieser Reihenfolge) ausgeben.

main.cpp

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <utility> /* ::std::pair */

int main()
{ auto p { ::std::make_pair( 3, 4 ) };
auto q { ::std::make_pair( 1, 2 ) };

/* Hier die Anweisung einsetzen! */

::std::cout << p.first << '\n';
::std::cout << p.second << '\n';
::std::cout << q.first << '\n';
::std::cout << q.second << '\n'; }

transcript
3
4
1
2

/   Übungsaufgabe

Schreiben Sie ein Programm, in dem ein Paar »o« angelegt wird, dessen erste Komponente ein int-Objekt ist und dessen zweite Komponente ein Paar zweier int-Objekte ist. Das Programm soll dann alle drei int-Unterobjekte, die in »o« enthalten sind, ausgeben. (Hier soll im gesamten Programm möglichst nur eine Variable definiert werden, nämlich »o«.)

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 stefanram721318 stefan_ram:721318 Paare in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd721318, slrprddef721318, 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/paare_c++