30.06.2013 Aufrufe

Softwareentwicklung in C++ - ASC

Softwareentwicklung in C++ - ASC

Softwareentwicklung in C++ - ASC

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

9.4 Weitere wichtige technische Aspekte 231<br />

wären statisch und nicht dynamisch gebunden. Dadurch würde Furchtbares<br />

passieren, nämlich dass ausschließlich der Destruktor von BaseA aufgerufen<br />

wird. Der Compiler hat ja statisch diesen Aufruf e<strong>in</strong>gefügt. Was allerd<strong>in</strong>gs<br />

passieren muss, damit das Programm korrekt funktioniert, ist, dass alle Destruktoren<br />

der e<strong>in</strong>zelnen Klassen <strong>in</strong> der Ableitungshierarchie korrekt aufgerufen<br />

werden. Genau das erreicht man nur, wenn man mit dynamic B<strong>in</strong>d<strong>in</strong>g<br />

arbeitet, also den Destruktor virtual deklariert. Damit wird zur Laufzeit<br />

entschieden, welcher der “tiefste” Destruktor des vorliegenden Objekts ist<br />

und von diesem ausgehend werden die anderen Destruktoren, die höher <strong>in</strong><br />

der Ableitungshierarchie liegen, korrekt aufgerufen.<br />

Vorsicht Falle: Die schweißtreibendsten Debug Sessions, an denen schon<br />

sehr viele Entwickler verzweifelt s<strong>in</strong>d, ergeben sich bei der Suche nach völlig<br />

unerklärlichen Effekten, die durch e<strong>in</strong>en statisch gebundenen Destruktor<br />

trotz dynamischer Verwendung von Objekten zustande kommen. Aus diesem<br />

Grund lautet die Grundregel Nummer e<strong>in</strong>s beim Entwickeln von C ++<br />

Programmen:<br />

Jede Klasse muss unbed<strong>in</strong>gt e<strong>in</strong>en virtual Destruktor besitzen!<br />

Auch wenn dies <strong>in</strong> manchen Fällen aufgrund der Verwendung als nicht<br />

notwendig ersche<strong>in</strong>t, so ist man auf jeden Fall bei E<strong>in</strong>halten dieser Regel<br />

immer auf der sicheren Seite. Vor allem passiert es oft genug, dass nach Programmänderungen<br />

Objekte polymorph verwendet werden, obwohl das zuvor<br />

beim Grunddesign der Klasse noch gar nicht der Fall und leider auch nicht<br />

mitgeplant war. Und genau dann kommt es garantiert zur Katastrophe. Zum<br />

Glück warnen moderne Compiler, wenn man <strong>in</strong> e<strong>in</strong>er Klasse virtual Methoden<br />

hat, aber den Destruktor nicht virtual deklariert.<br />

Nun zum eigentlichen Thema unseres Testprogramms: Es galt, herauszuf<strong>in</strong>den,<br />

wie die virtual Table aufgebaut (und auch wieder abgebaut) wird.<br />

Um festzustellen, welche Implementation der dynamisch gebundenen Methode<br />

gerade die “letzte aktive” <strong>in</strong> der virtual Table ist, wurden <strong>in</strong> die e<strong>in</strong>zelnen<br />

Konstruktoren und <strong>in</strong> die e<strong>in</strong>zelnen Destruktoren Outputs e<strong>in</strong>gebaut. Betrachtet<br />

man den Output, der beim Erzeugen von test_object entsteht, so<br />

kann man Folgendes beobachten:<br />

• Im Konstruktor von BaseA wird dynamicallyBoundMethod aufgerufen.<br />

Der tatsächlich ausgeführte Call ist die Implementation, die durch BaseA<br />

gegeben ist.<br />

• Im Konstruktor der davon abgeleiteten Klasse DerivedA erfolgt, wie man<br />

sieht, e<strong>in</strong> Aufruf der Implementation, die durch DerivedA vorgegeben ist.<br />

• Selbiges passiert <strong>in</strong> allen anderen Konstruktoren, die der Reihe nach bis<br />

zum fertigen Objekt aufgerufen werden.<br />

Was sagt uns das <strong>in</strong> Bezug auf die virtual Table? Nun, ganz e<strong>in</strong>fach: Die<br />

virtual Table wird sukzessive geme<strong>in</strong>sam mit dem Aufruf der Konstruktoren

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!