Glossar |
Dieses Glossar enthält Kurzdefinitionen der wichtigsten Begriffe der objektorientierten Programmierung und verwandter Bereiche. Das Glossar ist zum Nachschlagen und zur Wiederauffrischung der Begriffe gedacht, nicht zur Einführung. Entsprechende Textstellen können über das Stichwortverzeichnis gefunden werden.
Ein Abstrakter Datentyp fasst Daten und die Funktionen, mit denen die Daten bearbeitet werden dürfen, zusammen. Der Sinn liegt darin, den richtigen Gebrauch der Daten sicherzustellen. Mit »Funktion« ist hier nicht die konkrete Implementierung gemeint, das heißt, wie die Funktion im Einzelnen auf die Daten wirkt. Zur Benutzung eines Abstrakten Datentyps reicht die Spezifikation der Zugriffsoperation aus. Ferner sind logisch zusammengehörige Dinge an einem Ort konzentriert. Ein Abstrakter Datentyp ist ein → Typ zusammen mit → Datenkapselung. Eine → Klasse ist ein Abstrakter Datentyp, geschrieben in einer Programmiersprache.
Eine abstrakte Klasse ist eine → Klasse, von der es keine → Instanzen gibt. Abstrakte Klassen definieren → Schnittstellen, die durch abgeleitete Klassen implementiert werden müssen.
Die Aggregation ist ein Spezialfall der → Assoziation, der Enthaltensein (Teil-Ganzes-Beziehung) beschreibt. Wenn im Ganzen nur Verweise auf die Teile existieren, sind diese nicht existenziell abhängig vom Ganzen. Andernfalls spricht man auch von Komposition. In diesem Fall werden die Teile zusammen mit dem Ganzen zerstört. Zur Umsetzung in C++ siehe Seite 712.
Argument Dependent Lookup, kurz ADL, wird auch nach seinem Erfinder Koenig Lookup genannt. Es handelt sich um einen Algorithmus des Compilers, den Namespace von Funktionen aus dem Typ der Funktionsargumente zu ermitteln. Damit muss nicht immer der qualifizierte Name hingeschrieben werden:
Die Assoziation ist eine gerichtete Beziehung zwischen Klassen. Sie kann in eine Richtung verweisen (A kennt B, aber nicht umgekehrt) oder bidirektional sein (A kennt B und B kennt A).
Attribute beschreiben die Eigenschaften eines Objekts. Der aktuelle Zustand eines Objekts wird durch die Werte der Attribute beschrieben. Zum Beispiel kann Farbe ein Attribut sein; ein möglicher Attributwert wäre rot.
Eine Ausnahme (englisch exception) ist die Verletzung der → Vorbedingung einer Operation (→ Methode) einer Klasse. C++ bietet die Möglichkeit, Ausnahmen zu erkennen und zu behandeln (exception handling).
Datenstruktur zur Speicherung von Objekten. Beispiele: Array, Liste, Vektor
→ Intervall
→ dynamische Bindung, → statische Bindung
In der rein objektorientierten Programmierung wird davon ausgegangen, dass ein laufendes Programm(-system) aus einer Menge von Objekten besteht, die miteinander über Botschaften (englisch messages) kommunizieren. Ein genauerer Begriff als Botschaft ist Auf forderung, weil das empfangende Objekt etwas tun soll. Ein Objekt, das eine Aufforderung erhält, führt eine dazu passende Operation (→ Methode) aus, die in der → Klasse beschrieben ist.
Im informationstechnischen Sprachgebrauch heißen Dinge (Objekte, Rechner, ...), die eine Dienstleistung erbringen, Server. Die Dienstleistung wird erbracht für einen Client (deutsch: Klient, Kunde), der selbst ein Rechner oder Objekt sein kann.
→ Behälterklasse
Der Zustand eines Objekts wird durch seine Daten beschrieben. Die Daten sind die Werte der → Attribute eines Objekts.
Datenkapselung ist das »Verstecken« der Daten eines Objekts vor direkten Zugriffen. Zugriffe sind nur über die öffentliche → Schnittstelle der Datenkapsel (→ Abstrakter Datentyp) möglich. Datenbezogene Fehler sind damit leicht lokalisierbar. In C++ wird Datenkapselung mit der Zugriffsspezifikation private realisiert.
Eine Definition liegt vor, wenn mehr als nur der Name eingeführt wird, zum Beispiel wenn Speicherplatz angelegt werden muss für Daten oder Code oder die innere Struktur eines Datentyps beschrieben wird, aus der sich der benötigte Speicherplatz ergibt. Weil auch ein Name eingeführt wird, ist eine Definition immer auch eine Deklaration. Die Umkehrung gilt nicht.
Eine Deklaration teilt dem Compiler mit, dass eine Funktion (oder eine Variable) mit diesem Aussehen irgendwo definiert ist. Damit kennt er den Namen bereits, wenn er auf einen Aufruf der Funktion stößt, und ist in der Lage, eine Syntaxprüfung vorzunehmen. Eine Deklaration führt einen Namen in ein Programm ein und gibt dem Namen eine Bedeutung. Eine Deklaration kann gleichzeitig eine → Definition sein.
Ein Objekt wird durch den Aufruf einer Methode aufgefordert, eine Dienstleistung zu erbringen. Diese Aufforderung kann an ein weiteres Objekt zur Bearbeitung weitergeleitet (= delegiert) werden. In C++ kann auch ein Konstruktor seine Aufgabe an einen anderen Konstruktor delegieren.
Die Zusammenstellung von Programm(en) samt Dokumentation und anderen Dateien (Bilder, Audiodateien) in einer zur Verteilung geeigneten, in der Regel gepackten Form, wird Distribution genannt.
Wenn sich erst während des Programmlaufs ergibt, welche Methode für ein Objekt aufgerufen werden soll, kann das Binden noch nicht zur Compilier- oder zur Link-Zeit erfolgen, sondern eben erst später (englisch late binding). In C++ wird im Allgemeinen während der Übersetzung sichergestellt, dass nur zulässige Aufrufe einer Methode möglich sind (Ausnahme: siehe Beispiele zum dynamic_cast).
→ statisches Binden
Ein Objekt besitzt eine Identität, die es unterscheidbar macht von einem beliebigen anderen Objekt, selbst wenn beide gleiche Daten enthalten. Die Identität zu einem bestimmten Zeitpunkt wird durch eine eindeutige Position im Speicher gewährleistet; zwei Objekte können niemals dieselbe Adresse haben, es sei denn, ein Objekt ist im anderen enthalten. C++ hat keine Sprachmittel für die Identität. Die Adresse als Identitätsmerkmal gilt nur für ein → vollständiges Objekt und dann auch bei Mehrfachvererbung. Falls dies ausreicht, kann die Identität durch ein eigens für diesen Zweck vorgesehenes Element des Objekts definiert werden, zum Beispiel durch eine Seriennummer.
Wenn ein Objekt während der Erzeugung mit Anfangsdaten versehen wird, heißt der Vorgang Initialisierung. Die Initialisierung ist die Aufgabe eines Konstruktors. Sie ist von der → Zuweisung zu unterscheiden.
Eine Instanz einer Klasse ist eine andere Bezeichnung für ein → Objekt. Die Erzeugung eines Objekts wird auch Instanziierung genannt.
→ Schnittstelle
Oft müssen Bereiche angegeben werden. Dafür wird die in der Mathematik übliche Notation für Intervalle verwendet. Eckige Klammern schließen den Grenzwert ein, runde Klammern schließen ihn aus. So umfasst das Intervall [1, 4) die Werte 1, 2, 3. In C++ wird die Übergabe zweier Iteratoren an eine Funktion (Aufruf z.B. f(start, ende)) als Intervall [start, ende) interpretiert. Das heißt, ende kann in der Funktion als Endekriterium dienen, darf aber nicht dereferenziert werden. Zur Definition bei Ranges siehe Abschnitt 10.4.
Eine Klasse definiert die Merkmale (Daten) und das Verhalten (Operationen, Methoden) einer Menge von Objekten. Eine Klasse ist ein Datentyp, genauer: ein → Abstrakter Datentyp. In C++ gilt die Umkehrung (ein Datentyp ist eine Klasse) nicht, weil die Grunddatentypen (zum Beispiel int) und darauf aufbauende zusammengesetzte Typen (zum Beispiel C-Array) nicht als Klasse implementiert sind. Eine Klasse definiert die Struktur aller nach ihrem Muster erzeugten Objekte, entweder direkt oder indirekt durch → Vererbung.
Klassifikation ist ein Verfahren, um Gemeinsamkeiten von Dingen herauszufinden und auszudrücken. Von Unterschieden wird abstrahiert. In C++ wird ein Satz gleicher Merkmale und Verhaltensweisen durch die → Klasse beschrieben.
→ Zeitkomplexität
Ein lexikografischer Vergleich ist ein Vergleich, wie er bei der Sortierung von Begriffen in einem Lexikon verwendet wird. Danach entscheiden die jeweils ersten beiden Elemente zweier zu vergleichenden Folgen, welche Folge als kleiner aufgefasst wird. Falls jedoch die jeweils ersten Elemente gleich sind, werden die jeweils zweiten Elemente zum Vergleich herangezogen usw. Zum Beispiel würde bei den Zeichenfolgen »Objekt« und »Oberklasse« erst der dritte Buchstabe über die Sortierung entscheiden.
Beim statischen Linken werden die Bibliotheksmodule zu dem ausführbaren Programm gebunden. Die so erzeugte ausführbare Datei ist dementsprechend größer. Vorteil: Sie kann auf einen anderen Computer derselben Bauart und mit demselben Betriebssystemtyp kopiert werden und funktioniert dort wie auf dem Originalsystem. Nachteil: Wenn N Programme dieselbe statische Bibliothek benötigen, wird N mal der zugehörige Speicherplatz gebraucht, wenn die Programme gleichzeitig laufen.
Dynamisches Linken heißt, dass Bibliotheksmodule nicht in der ausführbaren Datei enthalten sind, sondern erst bei Ausführung des Programms dazugebunden werden. Vorteil: Wenn beliebig viele Programme dieselbe dynamische Bibliothek benötigen, wird der zugehörige Speicherplatz nur einmal gebraucht. Nachteil: Die ausführbare Datei funktioniert auf einem anderen Computer derselben Bauart und mit demselben Betriebssystemtyp nur, wenn die dynamische Bibliothek dort installiert ist.
Ein Literal ist eine unveränderliche Zeichenfolge im Programmcode, die direkt verwendet wird, wie zum Beispiel die Literale 1234 und true in den Anweisungen x = 1234; und bool wahrheitswert = true;. Verschiedene Literale können denselben Wert repräsentieren, etwa 15 und 0xf.
Ein L-Wert (Links-Wert, (englisch lvalue)) ist ein Ausdruck, der im Kontext seines Auftretens als (symbolische) Adresse eines Objekts oder einer Funktion aufgefasst werden kann. Die symbolische Adresse wird durch einen Namen repräsentiert. Eine Variable ist daher immer ein L-Wert. Ein (nicht konstanter) L-Wert kann auf der linken Seite einer Zuweisung auftreten, daher der Name. Ein L-Wert kann auch auf der rechten Seite einer Zuweisung auftreten, ein R-Wert sinnvoll jedoch nur auf der rechten Seite. Mehr Informationen finden Sie in Abschnitt 11.2.
Eine »magic number« ist eine Zahl, die als Literal mehrfach in einem Programm vorkommt. Bei Änderungen muss sie an mehreren Stellen aktualisiert werden, was einerseits fehlerträchtig ist und andererseits unnötige Arbeit verursacht. Besser ist es, sie durch eine Konstante, die ja nur einmal definiert wird, zu ersetzen.
Methode ist eine andere Bezeichnung für eine Operation, die auf den Daten eines → Objekts ausgeführt werden kann. In C++ heißen Methoden auch Elementfunktionen (englisch member functions), um auszudrücken, dass eine Methode ein Element einer Klasse ist. Sie unterscheidet sich von einer normalen Funktion auch dadurch, dass sie Zugriff auf die internen Daten des → Objekts hat.
Erlaubt es, Multimedia-Inhalte binären Formats an E-Mails zu binden. Der Inhaltstyp, oft MIME-Typ genannt, bestimmt die Art der Verarbeitung. Es können bei der IANA [MIME] registrierte Typen oder selbst definierte sein, die der vorgeschriebenen Syntax genügen. Der MIME-Typ wird nicht nur bei E-Mails, sondern auch in anderen Zusammenhängen verwendet (z.B. Browser).
Die Nachbedingung ist die Spezifikation einer → Methode, eines Programmschritts oder einer Funktion. Sie beschreibt ausgehend vom Zustand des Programms vor Ausführung (→ Vorbedingung), welchen Zustand ein Programm nach der Ausführung hat.
→ Botschaft
In einer Oberklasse werden Daten und Methoden spezifiziert, die mehreren (Unter-)Klassen gemeinsam sein sollen. Die öffentlichen Methoden definieren Schnittstellen, die auch für die Unterklassen gelten. Die Unterklassen werden dann als Spezialisierung der Oberklasse aufgefasst, weil sie nur noch die Unterschiede beschreiben. Zum Beispiel haben eine Tanne und eine Eiche die gemeinsame Eigenschaft, ein Baum zu sein mit all seinen Merkmalen. In einer Beschreibung (Klasse) für eine Tanne genügt es, auf die Oberklasse »Baum« zu verweisen (→ Vererbung) und nur die Besonderheit »Nadeln« anzugeben. Eine Oberklasse ist eine durch → Klassifikation gewonnene Abstraktion in der Form einer ist-ein-Beziehung. Ein Tanne »ist ein« Baum – eine Eiche auch. Eine Oberklasse kann selbst wieder von einer weiteren Oberklasse erben. Manchmal wird eine Oberklasse oder die oberste Oberklasse »Basisklasse« (englisch base class) genannt.
Ein Objekt ist die konkrete Ausprägung des durch eine → Klasse definierten Datentyps. Es hat einen inneren Zustand, der durch Attribute in Form von anderen Objekten oder Elementen der in der Programmiersprache vorgegebenen Datentypen dargestellt wird. Der Zustand kann sich durch Aktivitäten des Objekts ändern, also durch Ausführen von Operationen auf Objektdaten. Jedes Objekt hat eine Identität, sodass auch gleiche Objekte unterscheidbar sind. Im Ablauf eines Programms werden Objekte erzeugt (und wieder gelöscht), die aufgrund des Empfangs einer → Botschaft hin aktiv werden. Die Menge aller möglichen Botschaften für ein Objekt heißt → Schnittstelle.
Bei Open-Source-Software sind die Quellen, wie der Name sagt, frei zugänglich. Open-Source-Software ist meistens kostenlos. Sie kann modifiziert, kopiert und weitergegeben werden. Allerdings heißt Open Source nicht, dass alles erlaubt ist. Was erlaubt ist, ist nicht einheitlich geregelt, sodass es für verschiedene Open Source-Software unterschiedliche Lizenzen gibt. Die bekannteste ist die unter https://www.gnu.org/licenses/ erhältliche »GNU General Public License«.
→ Methode, → Botschaft
Die Fähigkeit von Programmelementen, sich zur Laufzeit auf → Objekte verschiedener → Klassen beziehen zu können, heißt dynamischer, Subtyp- oder Inklusions-Polymorphismus. Anders formuliert: Erst zur Laufzeit eines Programms wird die zu dem jeweiligen Objekt passende Realisierung einer Operation ermittelt. In C++ müssen diese Klassen in einer Vererbungsbeziehung stehen (→ Vererbung). Mit dieser Art Polymorphismus eng verknüpft ist der Begriff → dynamische Bindung. Wenn eine Klasse oder Funktion mit einem Parameter für den tatsächlich zu verwendenden Datentyp übergeben wird, spricht man von statischem oder parametrischem Polymorphismus. Dieser wird in C++ mit Templates realisiert.
Ein Objekt wird durch den Konstruktor initialisiert. RAII ist das Prinzip, Ressourcen durch die Initialisierung (das heißt durch den Konstruktor) zu belegen. Gleichzeitig ist damit die Freigabe der Ressource durch den Destruktor verbunden. Der Vorteil: Die Freigabe geschieht erst am Ende der Lebensdauer des Objekts. Sie erfolgt automatisch auch im Fehlerfall (Exception), ohne dass sie gesondert programmiert werden muss. Dieses Prinzip wird oft vorteilhaft eingesetzt. Beispiele: automatisches Schließen von Dateien, exception-sichere Beschaffung von Ressourcen mit shared_ptr.
→ L-Wert
Als (öffentliche) Schnittstelle (englisch (public) interface) bezeichnet man die Menge von Aufforderungen, auf die ein → Objekt reagieren kann. In C++ werden Schnittstellen durch die → Deklarationen der public- → Methoden beschrieben.
→ Client
SFINAE (substitution failure is not an error) bedeutet: Wenn die Substitution der Template-Argumente bei einem Template fehlschlägt, ist es kein Fehler, solange es ein anderes Template gibt, bei dem die Substitution gelingt. Beispiel siehe Abschnitt 13.5.1.
Die Signatur besteht aus der Kombination des Funktionsnamens mit der Reihenfolge und den Typen der Parameterliste. Anhand der Signatur kann der Compiler überladene Funktionen erkennen. Bei Funktions-Templates sind auch der umschließende Namespace und der Rückgabetyp Teil der Signatur. Und bei Elementfunktionen gehören u.a. const-Qualifizierer dazu, sofern vorhanden.
Ein std::string-Objekt speichert die Daten typischerweise auf dem Heap. Zur Erzeugung ist also eine new-Operation notwendig. Die Beschaffung von Speicher auf dem Heap mit new kostet normalerweise mehr Zeit als andere Operationen. Um das zu vermeiden, implementieren moderne Compiler die std::string-Klasse so, dass ein std::string-Objekt ein kleines Array enthält, zum Beispiel char[16]. Wenn ein String nun 15 Zeichen (plus 1 Nullbyte) oder weniger enthält, werden diese Zeichen direkt in diesem Array abgelegt. Eine new-Operation ist dann weder zur Erzeugung noch für die Kopie eines solchen Strings erforderlich – mit dem Ergebnis einer schnelleren Verarbeitung.
→ Dynamische Bindung
Ein Funktionsaufruf muss an eine Folge von auszuführenden Anweisungen gebunden werden. Der Aufruf einer Funktion (oder Methode, Operation) heißt statisch gebunden, wenn bereits der Compiler oder der Linker die Funktion einbindet, also vor dem Programmstart. Die Typverträglichkeit und Zulässigkeit von Funktionsaufrufen kann damit sehr früh geprüft werden. Siehe auch → Dynamische Bindung.
Ein Subtyp ist ein abgeleiteter → Typ, wobei ein Objekt eines Subtyps jederzeit an die Stelle eines Objekts der → Oberklasse treten kann. Ein abgeleiteter Typ, der nicht vollständig das Verhalten der Oberklasse zeigt, ist kein echter Subtyp.
Ein Typ ist die Menge aller Objekte in einem System, die auf dieselbe Art auf eine Menge von → Botschaften reagieren. Diese Objekte haben dieselbe öffentliche → Schnittstelle. In C++ wird ein Typ durch eine → Klasse beschrieben (ausgenommen Grunddatentypen wie int, bool, char usw.).
Die Unified Modeling Language (UML) ist eine weit verbreitete grafische Beschreibungssprache für Klassen, Objekte und noch mehr. Sie wird vornehmlich in der Phase des Softwareentwurfs eingesetzt. Grundlagen und Anwendung sind zum Beispiel in [Oe] beschrieben.
Eine Klasse, zu der eine → Oberklasse existiert, heißt Unterklasse bezüglich dieser Oberklasse. Wenn ein Objekt der Unterklasse stets an die Stelle eines Oberklassenobjekts treten kann, ist die Unterklasse ein → Subtyp der Oberklasse. Eine Unterklasse heißt auch »abgeleitete Klasse« (englisch derived class).
UTF steht für Unicode Transformation Format. UTF bildet Unicode-Zeichen auf Bytefolgen ab. In C++ gibt es UTF-8, UTF-16 und UTF-32. Ein UTF-8-Zeichen kann aus einem bis vier Bytes bestehen, ein UTF-16-Zeichen aus zwei oder vier Bytes und ein UTF-32-Zeichen besteht aus vier Bytes. Die zugeordneten String-Typen finden Sie in Abschnitt 8.9.1 auf Seite 411.
Vererbung wird definiert durch eine Beziehung zu einer → Oberklasse, um deren Merkmale und Verhaltensweisen zu übernehmen. Eine Klasse »erbt« von Oberklassen, indem die direkten Oberklassen in der Klassendefinition angegeben werden. Gleichzeitig wird damit von allen Oberklassen der Oberklasse geerbt, sofern sie existieren. Der Aufruf einer Operation für ein Objekt lässt nicht erkennen, ob sie der Klasse des Objekts oder einer Oberklasse zuzuordnen ist, also geerbt wurde.
Eine → Methode gewährleistet die Einhaltung ihrer Spezifikation, wenn der Aufrufer die → Vorbedingung einhält (zum Beispiel Aufruf der Methode mit korrekten Parametern). Die Methode erfüllt damit einen Vertrag.
Die exakte Bedeutung von volatile hängt von der Hardware ab. Damit ist volatile allenfalls für die sehr hardwarenahe Programmierung geeignet, aber nicht generell für die Thread-Programmierung.
Unter einem »vollständigen Objekt« wird ein Objekt verstanden, das nicht als Subobjekt dient, also nicht in einem anderen Objekt durch Vererbung enthalten ist.
Die Vorbedingung beschreibt den Zustand eines Programms, der notwendig ist, um den nächsten Programmschritt korrekt durchführen zu können. Der Programmschritt kann der Aufruf einer → Methode sein.
Der Begriff Komplexität aus der Informatik gibt an, wie die von einem Algorithmus benötigte Zeit und der benötigte Speicherplatz von der Anzahl der im Container gespeicherten Elemente abhängen. Meistens interessiert nur die benötigte Zeit (Zeitkomplexität). Von den Eigenschaften der Maschine, Betriebssystem und der Programmiersprache wird dabei abstrahiert. Letztere gehen mit einem konstanten Faktor ein. Die Zeitkomplexität von Algorithmen wird üblicherweise in der O-Notation angegeben. Dabei meint O(n), dass der Zeitaufwand proportional zur Anzahl n der Elemente (eines Containers) ist. O(logn) bedeutet, dass der Zeitaufwand proportional zum Logarithmus von n ist, und O(1), dass der Zeitaufwand konstant bzw. unabhängig von n ist.
Der Zustand eines Objekts ist definiert durch die Menge der Werte seiner → Attribute.
Eine Zuweisung weist ein Objekt dem anderen zu und ändert damit dessen Wert. Im Unterschied zur → Initialisierung muss das zu ändernde Objekt bereits existieren.
Eine Zusicherung (englisch assertion) ist eine logische Bedingung, die erfüllt sein muss. Zusicherungen dienen der Verifikation von Programmen, das heißt dem Nachweis, dass ein Programm seiner Spezifikation entspricht. Mit Zusicherungen können → Vorbedingungen und → Nachbedingungen geprüft werden.