Virtuelle Methode
-
Hallo,
Ich habe eine kurze Verständnisfrage zu Virtuellen Methoden einer Klasse.
Also ich habe eine Basisklasse (z.B Vogel) und mehrere Unterklassen (verschiedene Vögel), die von dieser Basisklasse erben. Doch meine Vögel singen alle verschieden, daher habe ich in jeder dieser Unterklassen eine Methode (Sing()), und zwar kommt diese in allen dieser Vögel vor.
Nun stellt sich mir die Frage, soll ich die Methode Sing() als virtuell deklarieren in der Basisklasse?
Was bringt das überhaupt?
Dankeschön!
-
Samyboy schrieb:
Nun stellt sich mir die Frage, soll ich die Methode Sing() als virtuell deklarieren in der Basisklasse?
Ja, solltest du.
Samyboy schrieb:
Was bringt das überhaupt?
Nehmen wir an, du hast einen Container voller verschiedener Vögel und lässt sie alle singen:
class Vogel { public: /*virtual*/ void Sing() { std::cout << "Piep!\n"} }; //hier diverse Ableitungen die verschieden singen... int main() { std::vector<Vogel*> voliere; voliere.push_back( new Papagei() ); //usw... for (std::vector<Vogel*>::iterator vit = voliere.begin(), end=voliere.end(); vit != end; ++vit) { (*vit)->Sing(); } }Wenn du hier das virtual weglässt, macht der Compiler zur Compilezeit daraus Nmal "Piep!", ansonsten wird zur Laufzeit ermittelt welche Sing()-Methode die richtige ist (d.h. von welchem Typ der Vogel tatsächlich ist) und du erhälst "Zwitscher!", "Tirili!", "Kuckuck!" usw

-
Dankeschön für die tolle Erläuterung!
Hat mir echt weitergeholfen

-
Wobei "Vogel" ja immer so ein schönes Beispiel ist. Nicht jeder Vogel kann singen, die Basisklassenmethode gibt's aber trotzdem.

-
pumuckl schrieb:
Nehmen wir an, du hast einen Container voller verschiedener Vögel und lässt sie alle singen:
Tierquälerei!!!
-
Ad aCTa schrieb:
Wobei "Vogel" ja immer so ein schönes Beispiel ist. Nicht jeder Vogel kann singen, die Basisklassenmethode gibt's aber trotzdem.

Naja, macht man entweder eine weitere Basisklasse Singvogel, oder findet sich mit der Tatsache ab dass manche Sing() Implementierungen einfach nix tun werden. Da einem sowas oft unterkommt, finde ich das Beispiel diesbezüglich wirklich recht realistisch.
-
Siehe "Effektiv C++ Programmieren". Wer auf Mehrfachvererbung oder Runtime-Errors verzeichten will, sollte Alternativen zu virtuellen Funktionen nutzen. (NVI-Idiom, Strategie-Muster)
-
Ad aCTa schrieb:
Wer auf Mehrfachvererbung oder Runtime-Errors verzeichten will, sollte Alternativen zu virtuellen Funktionen nutzen.
Den Zusammenhang verstehe ich jetzt nicht. Was ist falsch daran, gewisse Funktionen leer zu implementieren?
Nehmen wir an, ich habe ein GUI-Framework. Dabei hat jede Komponente eine Methode
OnEvent(), die bei irgendeinem ankommenden Event entsprechend ausgeführt wird. Da es nun auch Komponenten gibt, welche auf keine Events reagieren (z.B. passive Textanzeigen), lässt man deren Funktionen eben leer.
-
Ad aCTa schrieb:
Wobei "Vogel" ja immer so ein schönes Beispiel ist. Nicht jeder Vogel kann singen, die Basisklassenmethode gibt's aber trotzdem.

Laut Scott Meyers ist das ja auch i.O. Man macht die Basis-Methode entweder leer oder am besten pure virtual. Und der Vogeltyp der nicht singen oder fliegen kann (z.B. kann ein Pinguin nicht fliegen), implementiert einfach eine leere Methode. Und wird z.B.
vogel.fliegen()aufgerufen, passiert halt nichts.
-
Ad aCTa schrieb:
Siehe "Effektiv C++ Programmieren". Wer auf Mehrfachvererbung oder Runtime-Errors verzeichten will, sollte Alternativen zu virtuellen Funktionen nutzen. (NVI-Idiom, Strategie-Muster)
Das NVI-Idiom ist aber keine Alternative zu virtuellen Funktionen sondern eine Erweiterung, die die Bentutzung von virtuellen Funktionen sicherer macht.
Das Strategy-Patter wiederum benutzt selber virtuelle Funktionen, z.B. in der Strategie-Basisklasse. Also kann man auch hier nicht wirklich von Alternativen zu virtuellen Funktionen sprechen. Eine Sing-Stratey würde den Laufzeit-Polymorphismus nur eine indirektion weiter schieben. UNd Laufzeit-Polymorphie ohne virtuelle Funktionen geht nunmal nicht.
-
pumuckl schrieb:
UNd Laufzeit-Polymorphie ohne virtuelle Funktionen geht nunmal nicht.
Doch, sicher, z.B. mit Funktionszeigern

*duck-und-weg*