Überschriebene virtuelle Funktion: virtuell oder nicht?
-
Alternativ könnte man auch das override keyword benutzen (falls verfügbar), das würde für mich mehr Sinn ergeben.
Ist es allerdings nicht so, dass ein Aufruf von foo einer von Derived abgeleiteten Klasse mit einem Pointer auf Derived im ersten Beispiel Derived::foo aufruft, statt die Funktion der von Derived abgeleiteten Klasse? Im zweiten Beispiel sollte es doch korrekt laufen, oder irre ich mich da? Ist schon eine Weile her.
-
Cachus schrieb:
Ist es allerdings nicht so, dass ein Aufruf von foo einer von Derived abgeleiteten Klasse mit einem Pointer auf Derived im ersten Beispiel Derived::foo aufruft
Meinst du das?
class Base { virtual void foo() {std::cout << "base";} }; class Derived : Base { void foo() {std::cout << "derived";} };Nö. Einmal virtuell, immer virtuell.
#include <iostream> struct Base { virtual void foo() {std::cout << "base";} }; struct Derived : Base { void foo() {std::cout << "derived";} }; struct SecondDerived : Derived { void foo() {std::cout << "second-derived";} }; int main() { Base* a = new SecondDerived; a->foo(); }
-
Cachus schrieb:
Alternativ könnte man auch das override keyword benutzen (falls verfügbar), das würde für mich mehr Sinn ergeben.

Es gibt auch Compiler-Fehler, falls keine Funktion überschrieben werden kann. Allerdings fehlt mir der GCC-Support (wenn ich mich da nicht irre).
-
Ich meinte das eher so:
class Base { public: virtual void foo() {std::cout << "Base";} }; class Derived : public Base { public: void foo() {std::cout << "Derived";} }; class Derived2 : public Derived { public: void foo() {std::cout << "Derived 2";} }; int main(int argc, char *argv[]) { Derived2 d2; Derived* d = &d2; d->foo(); }Das gibt bei mir tatsächlich korrekt "Derived 2" aus, ist wohl doch schon länger her als ich dachte.
-
Hi,
wird eine Basisklasse angelegt die mindestens einen virtuellen Member hat,
so erzeugt der Kompiler für die Basisklasse, und folgend alle abgeleiteten
Klassen, eine Tabelle mit Addresseinträgen der, in der Basisklasse als virtuell
deklarierten, Methoden (auch virtuelle Tabelle genannt).Wird ein Derivat instanziiert bekommt diese die virtuelle Tabelle mit den
aktuellen Adresseinträgen (Im Basisklassensegment). Diese Tabelle entspricht auch einer Jumptable.Beispiel:
(skizzenhaft)class Base { public: virtual void foo() { __debugbreak(); }; void bar() { __debugbreak(); }; }; class Derived:public Base { void foo () { __debugbreak(); }; void bar() { __debugbreak(); }; }; void func_a(Base& blub) { blub.foo(); // wird durch derived ausgeführt blub.bar(); // wird durch base ausgeführt }; int _tmain(int argc, _TCHAR* argv[]) { Base b; Derived d; func_a(d); __debugbreak(); return 0; }Der Vorteil von Virtuellen Klassen ist, das diese überladene Methoden
des Derivats aus der Basis heraus aufrufen kannst, und das nur durch
die virtuelle Tabelle.
Die virtuelle Tabelle liegt vor dem eigentlichen datensegment
der instanz, also vor dem ersten Member.grüße
-
zeusosc schrieb:
VirtuellenKlassenPolymorphen Klassen
-
Kurze Ergänzung: Die "virtuelle Tabelle" nennen AFAIK die meisten Compiler
vtable, die fachsprachliche Abkürzung ist VMT (VirtualMethodTable). Einige Compiler liefern Fehler wieundefined reference to `vtable for VintagePort'
-
Japp und Japp

-
Hoffentlich gibts im neuen C++ Standard eine Möglichkeit nur Entpolymorphisierung.
-
Du meinst, eine virtuelle Funktion in abgeleiteten Klassen nicht mehr virtuell zu machen? Falls ja, was sollte das bringen?
-
Weil nicht-polymorphistische Methoden schneller im Aufruf sind.
-
xcall schrieb:
Weil nicht-polymorphistische Methoden schneller im Aufruf sind.
Nicht, wenn du es deinem Compiler nicht explizit verbietest, schlau zu sein.
Der gcc macht mir die virtuelle Funktion sogar inline, wenn er schnallt, dass kein late binding stattfindet. Das fand ich echt krass.
-
xcall schrieb:
Weil nicht-polymorphistische Methoden schneller im Aufruf sind.
Du kannst aber dennoch nicht einfach die Semantik ändern. Wenn die Funktion in der abgeleiteten Klasse nicht mehr virtuell wäre, aber über eine Basisklasse aufgerufen würde, was sollte dann passieren?
Erkläre das Ganze bitte ausführlicher. Bisher macht es eher den Anschein, dass du ein total unnützes Feature verfechtest, nur weil dir Performance-Mythen Angst machen.
-
Nexus schrieb:
xcall schrieb:
Weil nicht-polymorphistische Methoden schneller im Aufruf sind.
Du kannst aber dennoch nicht einfach die Semantik ändern. Wenn die Funktion in der abgeleiteten Klasse nicht mehr virtuell wäre, aber über eine Basisklasse aufgerufen würde, was sollte dann passieren?
Erkläre das Ganze bitte ausführlicher. Bisher macht es eher den Anschein, dass du ein total unnützes Feature verfechtest, nur weil dir Performance-Mythen Angst machen.
Ich denke, es ist so gemeint, wie ich es ursprünglich im Kopf hatte: Dass der virtuelle Aufruf nur stattfindet, wenn die Funktion in Klasse X des Pointers auf X noch virtuell ist, was dem Compiler als Optimierungshilfe dient. Es macht ja wenig Sinn, einen virtual function call durchzuführen, wenn bekannt ist, dass es keine überschreibung gibt.
Ist allerdings fragwürdig, ob das allein ausreicht um so ein Feature einzuführen.
-
Cachus schrieb:
Ist allerdings fragwürdig, ob das allein ausreicht um so ein Feature einzuführen.
Da Compiler diese Optimierung schon heute ohne dieses "Feature" durchführen, wohl eher nicht.
-
Auch wenn ein Compiler nicht alle Fälle optimieren kann, ist es wenigstens möglich den virtuellen Aufruf zu unterdrücken ( derivedObject.Base::foo() ), womit die Idee der "Entpolymorphisierung" allerdings hinfällig währe.