Die folgende Entwicklung zeigt, wie man, wieder ausgehend von C
die Mglichkeiten von C++ und danach die Mglichkeiten der
C++-Container-Bibliothek und der C++-Templates fr 
ein hherwertiges Problem verwendet.

Ein wichtiger Unterschied zwischen C und PASCAL ist, da in C die
Typenprfbarkeit mehr in der Verantwortung des Anwenders liegt
als in PASCAL.

Es gibt bewhrte Daten-Grundstrukturen, wie Listen, Bume, Verzeichnisse...,
die immer wieder nur mit anderen Variablentypen angewendet werden.
Um typenprfbare Programme zu schreiben, mu man den sehr sensiblen
Kode fr die Bearbeitung der Datenstrukturen immer wieder schreiben,
soda eine Wartung sehr umstndlich wird. 

In C gabs dafr die Notlsung, da man mit void-Pointern arbeitete und
mit einem cast-Operator die Typenrichtigkeit einstellte; nicht gerade
schn und auch nicht wirklich typensicher.

In C++ bleibt das Problem zunchst bestehen, man verwendet als einfachste
Lsung eine sogenannte Wrapper-Klasse LST6_.CPP, dann ist auch eine
Prprozessor-Lsung mglich, die diese Wrapper-Klasse automatisch aufbaut.

Die erste wirklich durch den Compiler berprfbare Typenreinheit erlauben die
Container-Klassen. LSTC_.CPP
Voraussetzung: die Datenstruktur mu vom Typ Object
abgeleitet sein. Dann kann man alle in der Containerbibliothek vorkommenden
Strukturen typensicher benutzen. Es ist von Nachteil, da man immer
an den Typ Object gebunden ist und, da man nur die vorhandenen Strukturen
einsetzen kann. Neue Strukturen erfordern Ergnzungen der Container-Bibliothek.

DIE Lsung diese Problems kam erst mit den Template-Klassen der
BORLAND-C++-Version 3.1 (ATT 2.1). Man kann entweder eine eigene
Template-Klasse fr eine Liste schreiben LST8_.CPP oder (bei Listen)
die bereits vorhandenen BIDS-Templates benutzen, LST9_.CPP. s


		 LST.H        LST.C
		 | LST5.H     | LST1.C
		 | | LST7.H   | | LST2.CPP
		 | | | LST8.H | | | LST3.CPP
		 | | | |      | | | | LST4.CPP
		 | | | |      | | | | | LST5.CPP
		 | | | |      | | | | | |
		 | | | |      | | | | | |
		 | | | |      | | | | | |
LST_     C       x            x
LST_1    C       x            x
LST1_    C                      x
LST2_    CPP                      x
LST3_    CPP                        x
LST4_    CPP                          x
LST5_    CPP       x                    x
LST6_    CPP       x                    x       Wrapper-Klasse
LST7_    CPP       x x                  x       Generische Klasse
LST8_    CPP       x   x                x       TEMPLATES (eigene)
LST9_    CPP                                    TEMPLATES (BIDS)
LST9_1   CPP                                    TEMPLATES mit Iterator
LSTC_    CPP                                    CLASSLIB - strings
LSTC_1   CPP                                    CLASSLIB - eigener Typ

LST.H

Je nach Aufgabe ist das Objekt OBJ, aus dem die Liste list
aufgebaut ein anderes.

LST.C

Ein Listenbestandteil ist ELEM,
der aus dem eigentlichen Inhalt o
der Typ von o wird zu Beginn als int festgelegt
und einem Zeiger next, der auf die nchste, gleichartige Struktur besteht.
Zeigt next auf NULL, dann handelt es sich um das letzte
Listenelement.

Die Liste selbst ist durch eine globale Variable list
dargestellt, die auf das erste Listenelement zeigt.
Am Beginn existiert noch keine Liste, list ist dieser Zeiger NULL

	+---------------------------+
	+-->+---+ +->+---+ +->+---+ |
	|   | o | |  | o | |  | o | |
	|   +---+ |  +---+ |  +---+ |
	|   |nxt|-+  |nxt|-+  |nxt|-+
  list--+   +---+    +---+    +---+
	      2        0        1

Verfahren, um mit der Liste umzugehen:
ein neues Element soll vorne oder hinten an die Liste
anhngbar sein (ins_head, ins_tail)
und vorne entfernbar sein (get_head)
auerdem mu die Liste insgesamt lschbar sein (clear)

Einfgen am Kopf, ins_head
	+------------------------------------+
	+-->+---+          +->+---+ +->+---+ |
	|   | o |          |  | o | |  | o | |
	|   +---+          |  +---+ |  +---+ |
	|   |nxt|-+        |  |nxt|-+  |nxt|-+
  list--+   +---+ |        |  +---+    +---+
	      3   |        |    1        2
		  |        |
		  +->+---+ |
		     | o | |
		     +---+ |
		     |nxt|-+
		     +---+
			 0

Einfgen am Ende, ins_tail
	+------------------------------------+
	+-->+---+          +->+---+ +->+---+ |
	    | o |          |  | o | |  | o | |
	    +---+          |  +---+ |  +---+ |
	    |nxt|-+        |  |nxt|-+  |nxt|-+
  list--+   +---+ |        |  +---+    +---+
	|     2   |        |    0        1
	|         |        |
	+---------+->+---+ |
		     | o | |
		     +---+ |
		     |nxt|-+
		     +---+
		       3

LST_.C

Alle Programme mit einem Unterstrich enthalten ein Hauptprogramm zum Testen.
LST_.C testet die Liste list durch Einfgen ganzer Zahlen am Anfang und
am Ende der Liste. Danach wird die Liste wieder geleert.

LST_1.C

Zeigt, wie man die einfache Liste auch fr allgemeinere Strukturen
verwenden kann.

Diese einfache Liste hat den Nachteil, da die
angewendete Algorithmen nur auf eine globale Variable list
anwendbar sind. Besser wre es, jeder Listenfunktion dieses list
als Parameter zu bergeben, womit man beliebig viele Listen
mit einem Funktionensatz bearbeiten knnte

LST1.C, LST1_.C

Merkmale dieser Vorgangsweise:
list wird zu einer lokalen Gre in main()
jede Funktion erhlt als Parameter die Liste list als Referenz
sowie das einzufgende Element

Welche Verbesserungsmglichkeiten bietet C++?

LST2.CPP, LST2_.CPP

(1) die Operatoren new und delete ersetzen malloc() und free()
(2) Parameterbergabe kann mittels Referenzen erfolgen
(3) struct ELEM kann ohne typedef als Typ ELEM verwendet werden
(4) Ein- und Ausgabe erfolgen ber streams

LST3.CPP, LST3_.CPP

Wie kann man Klassen in der Liste konstruieren?

(1) jedes Element der Liste ELEM kann eine Klasse sein
(2) die Liste selbst ist eine Klasse SLIST
(3) SLIST sei zunchst ffentlich

Mit diesen Schritten erreichen wir zunchst, da die redundanten
Zuweisungen zur Bildung eines neuen Elements in der Klasse ELEM
vom Konstruktor bernommen werden.


LST4.CPP, LST4_.CPP

Auch die Liste selbst kann eine Klasse werden LIST
Die bestehende Klasse ELEM entspricht eher einer Struktur,
da sie ffentlich zugnglich ist.
Daher wird das Zugriffsrecht auf die Klasse SLIST eingeschrnkt
Was gewinnen wir?
1. Jede Liste dieser Art wird automatisch richtig initialisiert
2. Niemand 'vergit' die Liste zu beseitigen, wenn sie nicht mehr
   gebraucht wird (Destruktor)
3. Die Benennung der Funktionen wird um eine Stufe einfacher, da
   der Klassenname die Zugehrigkeit angibt
4. Da list, die Wurzel der Liste globaler Klassenbestandteil ist
   und nicht mehr durch den Gltigkeitsbereich einer Funktion
   zu schtzen ist, entfllt die Parameterbergabe. Die Funktionen
   verhalten sich zueinander wie die C-Funktionen des einfachsten
   Listenprogramms ohne deren Nachteil zu besitzen, da die Variable
   list von auen nicht manipulierbar ist.
5. Eine zustzliche Prffunktion wird erforderlich, um feststellen
   zu knnen, ob die Liste leer oder voll ist (full())

LST5.H

Wir haben jetzt in rascher Folge eine Listenklasse in CPP erstellt
Wie kann man jetzt diese Klasse fr andere Typen
als es ein int ist anwenden?
Zuerst ist es besser, statt einer Variablen selbst einen
Pointer vom Typ void * zu verwenden, das zeigt LST5_.H.

LST5.CPP, LST5_.CPP

LST5_.CPP Testet die beiden Dateien LST5.H und LST5.CPP
mit einer Variablen vom Typ int

Beachten Sie, da bei Verwendung von Zeigern statt der Variablen
selbst folgendes zu beachten ist:
  1. Das Informationsfeld ELEM der Liste bleibt optimal klein
  2. Dieselbe Information kann mehrfach in der Liste vorkommen
     ohne deshalb mehrfach Speicherplatz zu belegen
     (wichtig bei groen Strukturen)
  3. Dagegen mu die Variable am Heap generiert und danach wieder
     freigegeben werden.
  4. Durch die Verwendung eines void* in ELEM besteht keine
     Typenprfung.

Ein Problem ist nach wie vor die Typenprfung eines Listenelements.
Ein cast-Operator vor einem einzufgenden Element ist nur eine Notlsung.

Es stehen drei weitere Hilfsmittel zur Verfgung
1. Eine Wrapper-Klasse          LST6_
2. Eine Prprozessor-Lsung     LST7_
3. Templates                    LST8_, LST9_
4. Container-Klassen            LSTC_, LSTC_1

Wenn auch die Templates die modernste Lsung sind und erst ab BC-3.1
untersttzt werden, sollte man doch auch die anderen Mglichkeiten kennen,
da sie doch immer wieder bei bestehendem Kode verwendet werden.

Ergnzend sei bemerkt, da man es natrlich auch wie in C machen knnte
und man den Typ OBJ jeweils umdefiniert.

LST6_.CPP

Wrapper Klassen

Man leitet von den bestehenden Klassen durch Vererbung eine neue Klasse
ab, die einen neuen Typ enthlt.

Das folgende Beispiel zeigt die Verwendung
einer Wrapper-Klasse SLIST, die der ursprnglichen Klasse LIST
einen prfbaren Typ, hier char* auferlegt.

Die Wrapper-Klasse hat den Nachteil, da der einleitende Kodeteil
fr jeden benutzen Typ zu wiederholen ist.

Da hier eine struct verwendet wird, soll nicht weiter stren,
es sind ja alle Bestandteile ffentlich, also kein Grund zur
Geheimhaltung; sonstiges Verhalten wie das einer Klasse.

LST7.H, LST7_.CPP

Generische Klassen

Nur eine Zwischenlsung auf dem Weg zu den Templates ist die
Anwendung eines declare-Makro.

Das folgende Beispiel zeigt die Verwendung
einer generischen Klasse SLIST.
Der Vorteil dieser Lsung verglichen mit dem Beispiel LST6_
ist die einmalige Erfassung und die beliebige Anwendung
auf verschiedene Typen, im Beispiel wiederholen wir die
String-Version.

LST8.H, LST8_.CPP

Template Klassen

Die modernste Lsung fr typenreine Konstruktionen,
wie in unserem Beispiel die Listen sind Template-Klassen.

LST9_.CPP

BIDS-Klassen

Noch einfacher ist es, den eigenen - in mancher Hinsicht noch
unvollstndigen - Kode zu verwerfen und auf die bestehende
Klassenbibliothek zurckzugreifen.

LST9_1.CPP

Liste mit Iterator

Statt der zerstrenden Benutzung der Liste kann auch
ein Iterator verwendet werden:

LSTC_.CPP

Liste mit Container-Klassen

Verwendet man von vornherein ein 'Objekt'-kompatibles Objekt,
hier Strings und setzt sie in eine Container-Liste, vermeidet man
die Typenproblematik.


LSTC_1.CPP

Im vorigen Beispiel war es sehr einfach ein Container-Objekt zu bilden,
da es eine von Object abgeleitete Klasse String gibt, die man unmittelbar
verwenden kann.
Nehmen wir an - und das wird wohl der hufigere Fall sein -
unsere Datenstruktur ist nicht vom Typ Object. Was dann?

CONOBJ.CPP

Ein einfhrendes Beispiel soll mit ganzen Zahlen zeigen, wie man
ein Klasse intObject aus Object ableitet und mit dem ntigen
Drumherum versieht.

LSTC_1.CPP

Kehren wir zu einem unserer ersten Beispiele zurck, wo wir es mit
Personen mit Namen und Telefonnumer zu tun hatten. Strukturen mit Platz
fr zwei Strings. Es ist zwar etwas komplizierter als eine ganze
Zahl aber durch den Vergleich sicher einfach zu verallgemeinern.


CONASS.CPP

Den Abschlu bildet ein kleines Beispiel mit einer Association,
einer paarweisen Anordnung von Eintragungen.


