006
15.07.2003, 15:53 Uhr
virtual
Sexiest Bit alive (Operator)
|
Oh, diesen interessanten thread hab ich ja ganz aus den Augen verloren .
Ich würde mich auch zur Fraktion StefanD und wissender zuordnen: Polymorphie und Überladen sind zwei verschiedene Dinge.´
Beim Überladen wird im Wesentlichen dem Programmierer einfach nur die Last abgenommen, sich jedesmal neue Methoden/funktionsnamen auszudenken. Überladen funktioniert auch unabh. von Klassen (im Gegensatz zur Polymorphie). Während ein C Programmierer schreiben müsste:
C++: |
char* int_zahl_zu_string(int z) { /* Konvertiere int in einen string */ }; char* float_zahl_zu_string(float z) { /* Konvertiere float in einen string */ };
|
Ist es einem C++ Programmierer Erlaubt zu schreiben:
C++: |
char* zahl_zu_string(int z) { /* Konvertiere int in einen string */ }; char* zahl_zu_string(float z) { /* Konvertiere float in einen string */ };
|
Dh. in C++ ist neben dem Funktionsnamen auch die Parameterliste dafür verantwortlich, daß das die richtige routine aufgerufen wird. In der letzteren Variante kann man sich problemlos auch noch vorstellen, daß die Funktionen innerhalb einer Klasse deklariert wurden: die Parameter entscheiden, welche Funktion aufgerufen werden.
Polymorphie arbeitet anders. Hier erst mal ein nicht polymorphes Beispiel:
C++: |
class base { .... public: void f() { std::cout<<"base::f()"<<std::endl; } }; class derived:public base { .... public: void f() { std::cout<<"derived::f()"<<std::endl; } };
void g(base& a) { a.f(); }
int main() { base x; derived y; g(x); g(y); }
|
Dieses Programm würde ausgeben:
An g wird ein Objekt eine variable des Types base übergeben und - da die Methode nicht polymorph ist - wird auch immer base::f() aufgerufen, und das, obwohl wir uns die Mühe gemacht haben, diese Method zu überschreiben! Polymorph wird das ganze durch das C++ Schlüsselwort virtual (nicht zu verwechseln mit mir! ):
C++: |
class base { .... public: [b]virtual[/b] void f() { std::cout<<"base::f()"<<std::endl; } }; ...
|
Nun ist die Methode virtuell, dh. es ist nicht der formale Typ in der Parameterliste von g davon abhängig, welche Version aufgerufen wird, sondern der aktuelle typ. Die ausgabe wäre "plötzlich":
Code: |
base::f() derived::f()
|
Funktionen kann man mithin nicht virtuell machen, wohl aber kann man virtuelle Methoden zusätzlich noch überladen. Es gibt jedoch einige Schüße ins Bein, die man sich so antun kann: Obiges Beipiel würde zB nicht funktionieren, wenn g(base& a) nicht eine Referenz (oder alternativ Pointer) übergeben würde, sondern ein Call By Value gemacht würde:
Dann kann man virtual verwenden, soviel man lustig ist, es würde sich nicht polymorph verhalten. (Der Grund ist einfach: beim Aufruf von g würde der Copyconstructor von base aufgerufen, welcher eben auch nur ein base-Objekt erzeugt. Selbst wenn ein derived-Objekt übergeben würde, würde der spezialisierte Teil "verschluckt"). -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) |