Methode der Basisklasse wird mit und ohne 'virtual' überschrieben
-
Hallo,
in der Überschrift steht bereits das Problem. Obwohl ich eine Methode der Basisklasse nicht als virtual kennzeichne wird diese von der abgeleiteten Klasse überschrieben;
Basisklasse:
class Zahl { public: string str() const; };bzw
class Zahl { public: virtual string str() const; };string Zahl::str() const { return "Eine unbekannte Zahl"; }Die abgeleitete Klasse:
class GanzeZahl : public Zahl { private: int zahl; public: GanzeZahl(int zahl); string str() const; }; GanzeZahl::GanzeZahl(int zahl) { this->zahl=zahl; } string GanzeZahl::str() const { stringstream ss; ss << zahl; return ss.str(); }int main() { GanzeZahl gz(1234); cout << gz.str() << endl; Zahl z(gz); cout << z.str() << endl; return 0; }Egal ob ich das Schlüsselword virtual verwende oder nicht, die Ausgabe der Konsole ist die gleiche.
Und wo ich schonmal hier bin... warum akzeptiert Zahl eine ganze Zahl als Parameter des Konstruktors? Was passiert da? Es ist kein Konstruktor definiert oder deklariert.
Vielen Dank schonmal.
-
VirtualStatic schrieb:
Hallo,
in der Überschrift steht bereits das Problem. Obwohl ich eine Methode der Basisklasse nicht als virtual kennzeichne wird diese von der abgeleiteten Klasse überschrieben;
Nein, sie wird überdeckt.
int main() { GanzeZahl gz(1234); cout << gz.str() << endl; Zahl z(gz); cout << z.str() << endl; return 0; }Beim ersten wird GanzeZahl::str und beim zweiten Zahl::str aufgerufen. Versuch mal so:
GanzeZahl gz(1234); Zahl& z = gz; z.str()Mit virtual wird die Methode von GanzeZahl, ohne virtual die von Zahl aufgerufen.
Und wo ich schonmal hier bin... warum akzeptiert Zahl eine ganze Zahl als Parameter des Konstruktors? Was passiert da? Es ist kein Konstruktor definiert oder deklariert.
Das ist der automatisch erzeugte Kopierkonstruktor. Dabei gibt es übrigens sog. Slicing, d.h. es werden nur die Basisklassenanteile kopiert.
-
Es wird nicht überschrieben, sondern überdeckt/versteckt.
#include <iostream> struct Base { void hide() const { std::cout << "Base::hide\n"; } virtual void override() const { std::cout << "Base::override\n"; } }; struct Derived : Base { void hide() const { std::cout << "Derived::hide\n"; } void override() const { std::cout << "Derived::override\n"; } }; int main() { Derived d; d.hide(); // Derived::hide d.override(); // Derived::override Base* pb = &d; pb->hide(); // Base::hide pb->override(); // Derived::override Base b; b.hide(); // Base::hide b.override(); // Base::override return 0; }Bei einer verstecken/überdeckten Methode ist der statische Typ der Variable entscheidend, was aufgerufen wird.
VirtualStatic schrieb:
Und wo ich schonmal hier bin... warum akzeptiert Zahl eine ganze Zahl als Parameter des Konstruktors? Was passiert da? Es ist kein Konstruktor definiert oder deklariert.
Zahlerstellt automatisch einen Kopierkonstruktor, welcher einenZahl const&Parameter hat. Daher kannst du auch ein Objekt vonGanzeZahlübergeben. Dabei entsteht aber ein Object-Slicing, also nur der Teil der BasisklasseZahlvonGanzeZahlwird kopiert und der Rest ignoriert. Sehr gefährlich
Grüssli
Edit: Schreibfehler. Wo hab ich bloss meinen Duden hingelegt?

-
Du hast denke ich den Sinn von virtuellen Funktionen nicht ganz verstanden.
Der Sinn ist ohne zu wissen, was für eine Ableitung von Zahl sich genau hinter einem Zeiger auf
Zahlund trotzdem die richtige Funktion aufzurufen.int main() { GanzeZahl gz(1234); Zahl* z = &gz; cout << z->str (); }Da wird der obwohl der statische Typ Zahl ist das str von GanzeZahl aufgerufen, weil der dynamische Typ GanzeZahl ist.
-
Super!
Vielen Dank an Euch! *****
-
Dravere schrieb:
Edit: Schreifehler. Wo hab ich bloss meinen Duden hingelegt?

Ohne Kommentar

(Und nächstes mal bitte nicht so laut :p)
-
l'abra d'or schrieb:
Dravere schrieb:
Edit: Schreifehler. Wo hab ich bloss meinen Duden hingelegt?

Ohne Kommentar

(Und nächstes mal bitte nicht so laut :p)Ich glaube langsam, dass ich zu schnell schreibe und meine Tastatur verschluckt die Buchstaben. Was da immer an Buchstaben verloren gehen, unglaublich!
:pGrüssli