Eine Klasse
ist dabei eine Erweiterung der bekannten struct
.
Darin werden nicht nur Daten deklariert, sondern auch die zugehörigen
Funktionen (Elementfunktionen,
Methoden)
einschließlich Initialisieren, Löschen, Kopieren und anderer
Operationen auf den Objekten. Eine Klasse ist also die Definition
eines Datentyps inklusive der Definition oder der Deklaration der
Operationen (Memberfunktionen). Ein Objekt dieser
Klasse, also eine mithilfe der Klasse vereinbarte Variable oder
allokierter Speicherplatz,
wird als Instanz der Klasse bezeichnet.
Durch die Möglichkeit, an eine Datenstruktur gleich die zugehörigen Funktionen anzuhängen, ist es recht einfach, die interne Datenstruktur vor dem eigentlichen Anwender der Daten zu verbergen und den Zugriff auf die Daten nur über Funktionen zuzulassen. Dies ermöglicht spätere Änderungen der Funktionsweise einer Klasse, ohne die Anwendung der Klasse ändern zu müssen, solange die Schnittstelle der Funktionen gleich bleibt (oder nur erweitert wird).
Vererbung
bedeutet, daß man zur Schaffung einer
Klasse (also die Weiterentwicklung einer
aus C bekannten struct
) ihre Eigenschaften nicht komplett
neu definieren muß, wenn eine ähnliche Klasse bereits existiert.
In einem solchen Fall kann man die neue Klasse aus der bereits existierenden
(der sogenannten Basisklasse)
ableiten. Die abgeleitete Klasse erbt alle Eigenschaften
(Daten- und Funktionsdeklarationen) der Basisklasse. Nur Zusätze oder
Änderungen gegenüber der Basisklasse müssen explizit beschrieben werden.
So kann man -von einfachen Basisklassen ausgehend- eine Hierarchie
von mehr oder weniger komplexen Klassen aufbauen und Erweiterungen
relativ leicht implementieren, ohne bestehende Klassen manipulieren zu müssen.
Polymorphie von Funktionen und Operatoren bedeutet, daß Aufrufe von Funktionen beziehungsweise die Wirkungsweise von Operatoren vom Zusammenhang abhängen, in dem sie auftreten. So kann beispielsweise die Addition von komplexen Zahlen oder der Sinus einer komplexen Zahl anders definiert werden, als die entsprechenden Operationen mit reellen Zahlen. Der Compiler kann bei mehreren gleichnamigen Funktionen, die sich in ihrer Parameterliste (in der Reihenfolge der Parametertypen oder in der Anzahl der Parameter) unterscheiden, je nach den aktuellen Parametern die richtige Funktion aussuchen. Man kann also eine jede Funktion mit einer weiteren überladen, die sich in der Parameterliste unterscheidet. Ebenso können Operatoren mit Funktionen überladen werden, wenn sich die Parameter der Funktion beziehungsweise die Operanden von den bisherigen Definitionen unterscheiden. Nicht möglich ist es allerdings, Operatoren mit einer anderen Anzahl von Operanden zu überladen. Ebenfalls nicht möglich ist es, die Prioritäten der Operatoren untereinander zu verändern. Weiterhin ist es ausgeschlossen, die Operatoren von eingebauten Basisdatentypen zu überladen.
Objektorientiertes Programmieren bedeutet also, nicht Funktionen mit Daten zu füttern (funktions- oder aktionsorientiert), sondern stattdessen die Daten (also die Objekte) direkt zu benennen, und über sie die zugehörigen Aktionen zu veranlassen, weil ja die Funktionen über die Definition der Klassen direkt an die Objekte gebunden sind. Da ein Funktionsaufruf damit an ein bestimmtes Objekt gebunden ist, wird dafür auch oft die Vorstellung bemüht dem Objekt eine Nachricht zu senden. Ich verwende allerdings weiterhin die Bezeichnung Funktionsaufruf beziehungsweise Methodenaufruf, weil es technisch gesehen genau das ist.
Für größere Projekte ist es sinnvoll, Klassen in eigenen
Klassenbibliotheken2.1zusammenzufassen. Insbesondere ist es sehr zweckmäßig, für alle
Objekte einer Klasse gegebenenfalls eine automatische Initialisierung
beim Erzeugen und automatische Aufräumfunktionen beim Freigeben
von Objekten definieren zu können. Dies erhöht die sichere Anwendung
von Klassen drastisch. Der Anwender, der ein Objekt einer Klasse
schaffen will, vereinbart einfach eine Variable oder schafft
ein Objekt mit new
(analog zum malloc()
in einem C-Programm).
Damit wird ohne sein Zutun die zugehörige Initialisierung des Objekts
durchgeführt (der Konstruktor wird aktiviert),
die der Programmierer der Klasse dafür vorgesehen hat.
Entsprechend wird beim Verlassen des Gültigkeitsbereichs der Variablen
oder beim Freigeben des Speichers mit delete
(als Gegenstück zu
new
) die Funktion zum Aufräumen des Objekts aufgerufen.
AnyWare@Wachtler.de