forward-declarations braucht man zum Beispiel bei solchen Abhängigkeiten
wie oben. Manchmal kommt es eben doch vor (auch wenn es dann häufig ein
besseres Design geben mag), dass zwei Klassen sich gegenseitig
benötigen.
Ein (ziemlich schlechtes) Beispiel:
Man hat zwei Klassen, die eine heißt DeviceContext, die andere
Rectangle. DeviceContext hat in etwa die Funktion eines HDC unter
Windows, stellt also eine Abstraktion der Zeichenhardware dar, meistens
des Bildschirms. Rectangle definiert ein Rechteck.
Der Einfachheit halber entscheidet man nun, dass Rectangle einen Zeiger
auf ein DeviceContext-Objekt erhält, um sich jederzeit selbstständig
zeichnen zu können. Ein DeviceContext-Objekt enthält nun aber
seinerseits ein Rectangle, um die gültige Zeichenfläche anzugeben.
Dieses Rectangle darf natürlich kein DeviceContext-Objekt enthalten,
sonst hätte man eine Endlosschleife (dieses Rectangle würde wieder ein
DC enhalten, dieses wieder Rectangle, und so weiter). Also enthält ein
DeviceContext ein Rectangle-Objekt, dessen DeviceContext-Zeiger auf 0
zeigt.
Um diese Klassen zu deklarieren, benötigt man zwingend
forward-declarations:
class DeviceContext;
class Rectangle {
DeviceContext* dc_;
public: Rectangle(DeviceContext* p) : dc_(p) { };
};
class DeviceContext {
Rectangle valid_area_;
public: DeviceContext() : valid_area(0) { };
};
DeviceContext initialisiert den dc_-Zeiger seines Rectangles also mit 0
(der Doppelpunkt beim Konstruktor leitet eine Initialisiererliste ein).
Wichtig ist hier, dass es andersrum nicht funktionieren würde; man kann
also nicht DeviceContext vor Rectangle definieren. Die
DeviceContext-Klasse enhält nämlich eine Rectangle-Instanz, keinen
Zeiger. Eine Instanz darf aber erst verwendet werden, nachdem die
Klasse vollständig definiert wurde. Der Compiler weiß ansonsten nicht,
wie viel Bytes er für DeviceContext reservieren soll (da er die Größe
von Rectangle noch nicht kennt).