- Inkapsulation und Erweiterungsfaehigkeit der Typen
- Vererbung
- Polymorphismus
- Überladen
- Virtuelle Funktionen
- Statische Klassenmitglieder
- Funktionstemplates
- Klassentemplates
- Abstrakte Klassen
Virtuelle Funktionen
Das Schlüsselwort virtual dient als Funktionsspezifikator, der Mechanismus für dynamische Auswahl in der Etappe der Ausführung der passenden Funktion-Glied unter Funktionen der Basis- und sekundaeren Klasse, Strukture können keine virtuelle Funktionen haben. Es kann erst für die Änderung Erklärung der Funktionen-Glieder verwendet werden.
Virtuelle Funktion muss wie eine normale Funktion ausfürenden Körper haben. Beim Aufruf hat sie dieselbe Semantik, wie andere Funktionen. .
Virtuelle Funktion kann in der sekundaeren Klasse substituiert werden. Die Auswahl der Funktionsdefinition erfolgt dynamisch (in der Ausführungsetappe). Typischer Fall - wenn die Basisklasse virtuelle Funktion hat, und sekundaere Klassen ihre eigenen Versionen dieser Funktion haben.
Anzeiger auf die Basisklasse kann entweder auf das Objekt der Basisklasse oder auf das Objekt der sekundaeren Klasse hinweisen. Auswahl der aufgerufenen Funktion-Glied wird in der Ausführungsetappe durchgeführt und wird vom Objektyp und nicht vom Anzeigertyp abhängig. Beim Fehlen des Gliedes des sekundären Typs wird vorbestimmt virtuelle Funktion der Basisklasse verwendet.
Destruktors sind immer virtuell unabhängig davon, ob sie mit dem Schluesselwort virtual erklärt werden oder nicht.
Betrachten wir die Verwendung von virtuellen Funktionen am Beispiel des Programms MT5_Tetris.mq5. In einschliessender Datei MT5_TetrisShape.mqh ist die Basisklasse CTetrisShape mit der virtuellen Funktion Draw (zeichnen) bestimmt.
//+------------------------------------------------------------------+
|
Weiters wird diese Funktion für jede sekundaere Klasse realisiert entsprechend den Besonderheiten der Klasse-Nachfolger. ZB. hat die erste Figur CTetrisShape1 ihre eigene Realisierung der Funktion Draw():
class CTetrisShape1 : public CTetrisShape
|
Figur Quadrat ist von der Klasse CTetrisShape6 beschrieben und hat ihre eigene Realisierung der Methode Draw():
class CTetrisShape6 : public CTetrisShape
|
Abhängig davon, Objekt welcher Klasse erzeugt wird, wird virtuelle Funktion einer oder anderer sekundären Klasse aufgerufen.
void CTetrisField::NewShape()
|
Modifier Override #
Der override Modifier bedeutet, dass die zu deklarierende Funktion die Methode der Basisklasse unbedingt überschreiben muss. Dank diesem Modifier kann man Fehler beim Überschreiben vermeiden, wie z.B. zufällige Änderung der Methodensignatur. In der Basisklasse ist zum Beispiel die Methode func definiert, die die Variable vom Typ int als Argument hat:
class CFoo |
Weiter wird die Methode in der abgeleiteten Klasse überschrieben:
class CBar : public CFoo |
Aber durch einen Fehler ändert sich der Typ des Arguments von int zu short. In diesem Fall wird die Methode nicht mehr überschrieben, sondern überladen. In einigen Situationen kann der Compiler entsprechend dem Algorithmus der überladenen Funktion statt der überschriebenen Methode eine in der Basisklasse definierte Methode auswählen.
Um solche Fehler zu vermeiden, sollte man der Methode den override Modifier hinzufügen.
class CBar : public CFoo |
Wenn die Signatur beim Überschreiben geändert wird, kann der Compiler keine Methode mit der gleichen Signatur in der Basisklasse finden und gibt einen Kompilierungsfehler aus:
'CBar::func' method is declared with 'override' specifier but does not override any base class method |
Modifier final #
Der Modifier final funktioniert umgekehrt: er verbietet, Methoden in abgeleiteten Klassen zu überschreiben. Wenn die Implementierung der Methode abgeschlossen ist, deklarieren Sie diese mit dem Modifier final, damit sie später garantiert nicht verändert wird.
class CFoo |
Beim Versuch, die Methode mit dem final Modifier zu überschreiben, gibt der Compiler eine Fehlermeldung aus:
'CFoo::func' method declared as 'final' cannot be overridden by 'CBar::func' |
Sehen Sie auch