Virtuelle Methoden, Vererbung und co.
-
hallo
ich wollte mal schauen ob ich verstehe wie virtuelle methoden wirklich funktionieren und welche logik dahinter steckt. dafür habe ich euch ein kleines beispiel geschrieben, welches ich kommentiert habe. bitte achtet genau auf die kommentare weil diese meine eigentliches gelerntes demonstrieren.
zögert bitte nicht mir detailliert zu sagen wo ich einen fehler gemacht habe.
eine frage zur vererbung stelle ich gleich hier:spricht man sowohl von mehrfachvererbung wenn eine klasse von mehreren klassen abgeleitet wird und auch dann wenn eine klasse von mehreren klassen erbt?
und zuguter letzt: wenn ich alles richtig verstanden habe, in welchem stadium kann man sich dann sehen wenn es folgende möglichkeiten dafür gibt:
- anfänger kenntnisse
- gute anfänger kenntnisse
- mitten drin
- fortgeschrittene kenntnisse
- professinelle kenntnisse
- senior developer kenntnisseich danke euch!
//--------------------------------------------------------------------------- class Base { public: void Func1() { ShowMessage("Base::Func1 (non-virtual)"); } virtual void Func2() { ShowMessage("Base::Func2 (virtual)"); } }; //--------------------------------------------------------------------------- class Derrived : public Base { public: void Func1() { ShowMessage("Derrived::Func1 (non-virtual)"); } void Func2() { ShowMessage("Derrived::Func2 (von Base überschrieben)"); } virtual void Func3() { ShowMessage("Derrived::Func3 (virtual)"); } /* wenn hier nun Methoden wie Func3 als virtual deklariert werden, wird die abgeleitete Klasse von Derrived dann diese überschreiben. */ }; //--------------------------------------------------------------------------- class Derrived2 : public Derrived { public: void Func2() { ShowMessage("Derrived2::Func2 (von Base überschrieben)"); } void Func3() { ShowMessage("Derrived2::Func2 (von Derrived überschrieben)"); } }; //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { /* Der einsatz von virtuellen Methoden macht eigentlich nur hier sinn weil hier eine Instanz von Base erzeugt wird und mit der abgeleiteten Klasse Derrived() initialisiert. So können die nicht virtual Methoden von Base() als Base::Methode() ausgeführt werden und die virtuellen Methoden als Derrived::Methode(). */ Base *BD = new Derrived(); BD->Func1(); BD->Func2(); /* Auch hier macht es grossen sinn. Hier wird eine Instanz der Klasse Derrived erzeugt und mit der abgeleiteten Klasse Derrived2 initialisiert. Das Objekt DD2 welches von Derrived und Base abgeleitet wurde, verfügt nun über methoden der beiden Basis Klassen und über seine eigenen. Je nach dem wie die Basis Methoden deklariert wurden gibt es hier ein grosses Methoden-Mischverhältnis. */ Derrived *DD2 = new Derrived2(); DD2->Func1(); DD2->Func2(); DD2->Func3(); /* Hier haben virtuelle Methoden keinen nutzen, weil hier wird die Methode Fun1 und Func2 von Base() so oder so ausgeführt. */ Base *B = new Base(); B->Func1(); B->Func2(); /* Hier haben virtuelle Methoden keinen nutzen, weil hier wird die Methode Fun1 und Func2 von Derrived() so oder so ausgeführt. */ Derrived *D = new Derrived(); D->Func1(); D->Func2(); delete BD; delete DD2; delete B; delete D; BD = NULL; DD2 = NULL; B = NULL; D = NULL; }
-
Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
virtual_lek schrieb:
spricht man sowohl von mehrfachvererbung wenn eine klasse von mehreren klassen abgeleitet wird und auch dann wenn eine klasse von mehreren klassen erbt?
Den Begriff Mehrfachvererbung verwendet man nur wenn eine Klasse von mehreren anderen erbt. Zur Ergänzung: Und hier wird auch in einigen Sprachen noch eine Einschränkung gemacht, und zwar zwischen Interface- und Klassenvererbung (In Sprachen wie C# und Java ist Merhfachvererbung von Klassen nicht erlaubt, von Interfaces kann man aber dort beliebig ableiten).
Von den Kenntnissen würde ich dich auf Anfänger einstufen, die Beispiele sind auch nicht unbedingt gut beschrieben. Wenn ich das von dir richtig Interpretiere würde ich aber sagen, das du die Grundlagen verstanden hast.
Für Beispiele solltest du aber zum besseren Verständnis der Leser in einen Ansi C++ Forum dich auch auf eben dieses Beschränken, die C++ Builder spezifischen Konstrukte könnten den ein oder anderen (Anfänger) verwirren.
virtual_lek schrieb:
Der einsatz von virtuellen Methoden macht eigentlich nur hier sinn weil hier eine Instanz von Base erzeugt wird und mit der abgeleiteten Klasse Derrived() initialisiert.
Ganz so würde ich es nicht ausdrücken. Virtuelle Methoden spielen ihre Vorteile nur aus, wenn man unterschiedliche Klassen über eine gleiche Schnittstelle ansprechen will (Vererbung sollte dabei immer ein "Ist-Ein" bedeuen, z.B. Angestellter "ist eine" Person). Dennoch kann es auch Sinn machen mit Elemente der Basisklasse zu arbeiten:
class Person; class Angestellter : public Person; void SchreibeMailAn(Person const &);
Selbst wenn nun an SchreibeMailAn "nur" eine Person übergibt, macht der Aufruf durchaus Sinn, oder?
Noch eine Anmerkung:
virtual_lek schrieb:
[/cpp]
// ...
delete BD;
BD = NULL;
}
[/cpp]Wenn du einen Zeiger mit delete löschst, der ohnehin direkt anschließend (verlassen des Scopes) ungültig wird, so musst du ihn nicht auf NULL zurücksetzen. Solche Konstrukte machen nur Sinn, wenn diese Variable nochmal zugegriffen werden kann.
cu André
-
naja also schlecht ist das wenn ich das richtig sehe schonmal nicht
du benutzt den borland compiler kann das sein?
weil das __fastcall sagt mir eher weniger als VC++ Usernaja trotzdem würde ichd ich "nur" als guten anfänger einordnen, weil
1.- gibt es auch noch nette sachen mit polymorphie
2.- ungefähr so steht das in jeden zweiten tutorial, das ganze auch sinnvoll anwenden zu können ist die eigendliche schwierigkeitalles in allem du bist auf einem guten weg alles schön sauebr zuschreiben und auch einiges gebacken zu kriegen
-
virtual_lek schrieb:
spricht man sowohl von mehrfachvererbung wenn eine klasse von mehreren klassen abgeleitet wird und auch dann wenn eine klasse von mehreren klassen erbt?
Beides, weil erben gleichbedeutend mit ableiten ist.
virtual_lek schrieb:
und zuguter letzt: wenn ich alles richtig verstanden habe, in welchem stadium kann man sich dann sehen wenn es folgende möglichkeiten dafür gibt:
- anfänger kenntnisse
- gute anfänger kenntnisse
- mitten drin
- fortgeschrittene kenntnisse
- professinelle kenntnisse
- senior developer kenntnisseHm, schwierig zu sagen. Polymorphie ist zwar schon eher fortgeschritten, gehört aber meiner Ansicht nach schon auch noch zu den Grundlagen, weil es direkt ein Sprachfeature ist. Ich würde mal "mitten drin" tippen.
Folgende Antworten habe ich direkt in den Code geschrieben, um den Kontext zu bewahren. Antworten von mir beginnen mit einem "->".
//--------------------------------------------------------------------------- class Base { public: void Func1() { ShowMessage("Base::Func1 (non-virtual)"); } virtual void Func2() { ShowMessage("Base::Func2 (virtual)"); } }; //--------------------------------------------------------------------------- class Derrived : public Base { public: void Func1() { ShowMessage("Derrived::Func1 (non-virtual)"); } void Func2() { ShowMessage("Derrived::Func2 (von Base überschrieben)"); } virtual void Func3() { ShowMessage("Derrived::Func3 (virtual)"); } /* wenn hier nun Methoden wie Func3 als virtual deklariert werden, wird die abgeleitete Klasse von Derrived dann diese überschreiben. -> Ja, das stimmt. Normalerweise schreibt man aber Derived ;) */ }; //--------------------------------------------------------------------------- class Derrived2 : public Derrived { public: void Func2() { ShowMessage("Derrived2::Func2 (von Base überschrieben)"); } void Func3() { ShowMessage("Derrived2::Func2 (von Derrived überschrieben)"); } }; //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { /* Der einsatz von virtuellen Methoden macht eigentlich nur hier sinn weil hier eine Instanz von Base erzeugt wird und mit der abgeleiteten Klasse Derrived() initialisiert. -> Kommt drauf an. Virtuelle Methoden machen generell Sinn, wenn man einen Zeiger oder einer Referenz auf eine polymorphe Basisklasse hat. Du kannst auch eine Base erstellen, dann werden eben die entsprechenden Methoden von Base aufgerufen. So können die nicht virtual Methoden von Base() als Base::Methode() ausgeführt werden und die virtuellen Methoden als Derrived::Methode(). -> Ja. */ Base *BD = new Derrived(); BD->Func1(); BD->Func2(); /* Auch hier macht es grossen sinn. Hier wird eine Instanz der Klasse Derrived erzeugt und mit der abgeleiteten Klasse Derrived2 initialisiert. Das Objekt DD2 welches von Derrived und Base abgeleitet wurde, verfügt nun über methoden der beiden Basis Klassen und über seine eigenen. Je nach dem wie die Basis Methoden deklariert wurden gibt es hier ein grosses Methoden-Mischverhältnis. -> Ja, ist ja im Prinzip das selbe wie oben. */ Derrived *DD2 = new Derrived2(); DD2->Func1(); DD2->Func2(); DD2->Func3(); /* Hier haben virtuelle Methoden keinen nutzen, weil hier wird die Methode Fun1 und Func2 von Base() so oder so ausgeführt. -> Wenn man nur dieses Beispiel betrachtet, ja, dann haben sie keinen Sinn. */ Base *B = new Base(); B->Func1(); B->Func2(); /* Hier haben virtuelle Methoden keinen nutzen, weil hier wird die Methode Fun1 und Func2 von Derrived() so oder so ausgeführt. -> Ja, wieder analog zu oben. */ Derrived *D = new Derrived(); D->Func1(); D->Func2(); delete BD; delete DD2; delete B; delete D; BD = NULL; DD2 = NULL; B = NULL; D = NULL; }
-
Die oberen Beiträge hab ich noch nicht gesehen, als ich meinen abgeschickt habe. Das langsame Forum hat auch seinen Teil dazu beigetragen...
Naja, Hauptsache ich habe nicht zu viel wiederholt.
asc schrieb:
virtual_lek schrieb:
spricht man sowohl von mehrfachvererbung wenn eine klasse von mehreren klassen abgeleitet wird und auch dann wenn eine klasse von mehreren klassen erbt?
Den Begriff Mehrfachvererbung verwendet man nur wenn eine Klasse von mehreren anderen erbt.
Hm, wenn das so gemeint ist, dann stimmt das natürlich. Ich war mir nicht sicher, weil ableiten und erben synonym verwendet wird.
Nochmals zur Verdeutlichung:
"Seriell" abgeleitete Klassen - mit jeweils eine Basisklasse - gehen nicht unter Mehrfachvererbung.class Base {}; class Middle : public Base {}; class Derived : public Middle {};
"Parallel" abgeleitete Klassen - eine Klasse hat mehrere Basisklassen - bezeichnet man als Mehrfachvererbung. Es wird also von mehreren Klassen geerbt.
class Base1 {}; class Base2 {}; class Derived : public Base1, public Base2 {};
-
Nexus schrieb:
Hm, wenn das so gemeint ist, dann stimmt das natürlich. Ich war mir nicht sicher, weil ableiten und erben synonym verwendet wird.
Ich muss gestehen das ich auch den Urprungssatz mehrfach lesen musste, und glaube mit meiner Interpretation richtig zu liegen. Den ansonsten hätte er den Inhalt zweimal in einen Satz wiederholt.
Wenn ich richtig verstanden habe betrifft sein Punkt auch den folgenden Fall:
// Keine Mehrfachvererbung (Von der Basisklasse wird mehrfach abgeleitet) class A; class B : public A; class C : public A; // Mehrfachvererbung (Eine Klasse erbt von mehreren) class A; class B; class C : public A, public B;
cu André
-
asc schrieb:
// Keine Mehrfachvererbung (Eine Klasse erbt von mehreren) class A; class B; class C : public A, public B;
Was verstehst du denn dann unter Mehrfachvererbung? Oder hast du dich nur vertippt?
-
Nexus schrieb:
Was verstehst du denn dann unter Mehrfachvererbung? Oder hast du dich nur vertippt?
Ich war um 08:14 wohl noch am Schlafen, okay, das galt vom Gefühl her heute den ganzen Tag
P.S: Noch dazu der typische Copy-Paste Fehler (Copy-Paste der Fluch und Segen der Programmierer)
-
asc schrieb:
Ich war um 08:14 wohl noch am Schlafen, okay, das galt vom Gefühl her heute den ganzen Tag
Das kenne ich von irgendwo her...
Ist schon okay, ich hatte nur gerade Angst, mir wäre da was Wichtiges entgangen (passiert schliesslich genug oft).