virtual Ungewissheit
-
Diese beiden Klassen seien gegeben:
class Base{ // ... public: virtual void func(); }; class Middle{ // ... public: virtual void func(); };Jetzt möchte ich eine Klasse von Middle ableiten, für die es allerdings ausreichend wäre, wenn die Version von func() aus der Klasse Middle aufgerufen würde:
class Final{ // ... public: // Hier jetzt das Problem, wenn ich hier die Funktion noch einmal // deklariere, dann muss ich sie ja Final::func() noch einmal implementieren, // obwohl eigentlich ja die Version aus Middle() ausreichend // wäre. // Wenn ich die Funktion hier nicht deklariere, dann kennt der Compiler // Final::func() nicht // Als Gipfel des Eisbergs liegt die Implementierung der Funktion aus // Middle nur in kompilierter Version vor, Cut & Paste geht deshalb auch nicht };Gibt es die Möglichkeit, dass man die Funktion in Final noch einmal definiert, und dann von dort aus 'irgendwie' 'einfach' die Parameter an die Funktionsversion aus Middle weitergibt?
Oder wird hier irgend eine nicht vorhersehbare Version von func() aufgerufen:Base* T = new Final(); T->func(); // angenommen in Final ist func() nicht deklariert. // was geschieht dann? wird dann einfach irgend eine func()-Version // aus einer der Basisklassen aufgerufen ? // Und andernfalls, wenn man in Final die func() nun doch nocheinmal // anlegt, wie gelingt es dann, dass von dieser Final-func()-Funktion // aus zu einer func()-Version in einer der vorangegangenen Klassen // gesprungen wird ? // Irgendwie so: return ((Middle*)this)->func() ??? (C-Cast womöglich?)Thx für tipps
-
vorausgesetzt, die funktionen sind implementiert:
class Base{ // ... public: virtual void func(); }; class Middle : public Base { // ... public: virtual void func(); //func ist implizit virtual. virtual ist hier also überflüssig (weil base::func virtual ist) }; class Final : public Middle { }; int main () { Final f; f.func(); Base &b = f; b.func(); }ruft beide male middle::func auf.
probleme bekommst du, wenn du in Final eine funktion deklarierst, die middle::func verdeckt:class Final : public Middle { public: void func (int); };in diesem fall hast du die möglichkeit mit using middle::func wieder sichtbar zu machen:
class Final : public Middle { public: void func (int); using Middle::func; }Virtuall schrieb:
Base* T = new Final(); T->func(); // angenommen in Final ist func() nicht deklariert. // was geschieht dann? wird dann einfach irgend eine func()-Version // aus einer der Basisklassen aufgerufen ? // Und andernfalls, wenn man in Final die func() nun doch nocheinmal // anlegt, wie gelingt es dann, dass von dieser Final-func()-Funktion // aus zu einer func()-Version in einer der vorangegangenen Klassen // gesprungen wird ? // Irgendwie so: return ((Middle*)this)->func() ??? (C-Cast womöglich?)hier wird Middle::func aufgerufen. wenn func in Final nochmal definiert wird, wird Final::func aufgerufen. es wird immer diejenige funktion aufgerufen, die zum "richtigen" (dynamischen) typ gehört. wenn du innerhalb von final eine ganz bestimmte version von func aufrufen willst, kannst du folgendes machen:
void Final::func () { this->Middle::func(); //wahlweise auch ohne this-> this->Base::func(); }dasselbe funktioniert von außerhalb:
Final f; f.Middle::func(); f.Base::func();allerdings nicht bei zeigern auf die basisklasse:
Base *b = new Final; //b->Middle::func(); //fehler: Middle ist keine basisklasse von Base b->Base::func(); //das funktioniert natürlich schon und ruft Base::func auf. //hier kannst du mit dynamic_cast (oder static_cast, ist aber nur in bestimmten fällen richtig) downcasten und danach die gewünschte methode aufrufen: dynamic_cast<Final*>(b)->Middle::func(); //bspw. delete b;
-
Danke für die ausführliche Antwort!
