virtual



  • Sag bloß, du kennst keine P.I. Zeiger? Die speichern einen Funktionszeiger + Objektzeiger in 1 Byte rein und damit kann man virtual calls direkt machen, sogar mit weniger Speicherverbrauch als mit normalen Zeigern.

    PI-Zeiger ❤



  • 314159265358979 schrieb:

    Sag bloß, du kennst keine P.I. Zeiger?

    Sonst hätte ich wohl nicht gefragt.

    314159265358979 schrieb:

    Die speichern einen Funktionszeiger + Objektzeiger in 1 Byte rein und damit kann man virtual calls direkt machen, sogar mit weniger Speicherverbrauch als mit normalen Zeigern.

    Der Text bietet leider keine Referenz und auch nichts, nach dem man googeln könnte, wenn man wissen wollte, was das sein soll bzw wie es funktioniert.



  • Ach komm, dass das Blödsinn ist, ist dir doch bestimmt aufgefallen, oder? 🙂



  • @blurry: RTFM, STFW, GIYF. Was soll man da machen.

    Virtuelle Methoden funkionieren so:

    Für die dynamische Bindung wird zuerst im referenzierten Objekt der virtuelle Methoden-Zeiger auf die VMT(entsprechend der Klasse) ausgewertet, anschließend wird aus dieser die Adresse der virtuellen Methode verwendet. Da sagst du nich' dem Compiler, er soll nochmal genau nachschaun' was du willst.



  • Und was ist ein virtueller Methodenzeiger? :p



  • 314159265358979 schrieb:

    Und was ist ein virtueller Methodenzeiger? :p

    Da du so ein erfahrener und erfolgreicher Software-Entwickler bist, hast du die überaus große Ehre, das zu präsentieren. 😉 😃

    🕶



  • Ich hätte dich nicht gefragt, wenn ichs nicht wüsste. Virtueller Zeiger klingt aber voll toll. Erklär mal.



  • Wie wärs damit?:

    Ein virtueller Methodenzeiger ist ein vom Compiler erzeugter (also interner) Funktionszeiger, der je virtueller Methode jedes Objektes diesen zur Verfügung gestellt wird.



  • Und was ist an dem Zeiger nun virtuell?



  • Das er erst zur Laufzeit erzeugt (und dereferenziert wird).



  • Ein Zeiger der zur Laufzeit erzeugt wird? Erklär das mal genauer. 🤡



  • Meinst du die vtable?!



  • wtfwtf schrieb:

    Meinst du die vtable?!

    VMT <-> Virtual Method Table.

    Das er zur Laufzeit erzeugt wird, bedeutet im Endeffekt, dass der Programmierer keinerlei Kontakt mit ihm hat und ihn nicht Kontrollieren kann.
    Der Zeiger existiert nur vorübergehend, um die Relationen in den Stammbäumen der Klassen im Bezug auf Virtuelle Methoden korrekt auszugleichen.
    Du, Pi, hast auch schon mal versucht das nachzubauen.

    Ja, vtalble - so nennt Sie der Compiler.

    Undefined reference to 'vtable for MyClass::~Myclass()'
    

    oder so ähnlich, das hat ich schon öfter.



  • Und wie wird der erzeugt? Durch irgend einen Kobold oder so?



  • 314159265358979 schrieb:

    Und wie wird der erzeugt? Durch irgend einen Kobold oder so?

    Ja. Ein 2cm großer Kobold namens Grämlin sitzt in deinem PC und kackt Methodenzeiger. 🙄

    Nein, ohne witz mal. Ich glaub(weiß es aber nicht), der Zeiger wird vom Compiler erzeugt, und zeigt anfangs auf die Basisklassenmethode.



  • Du meinst wohl Gremlin.
    Wie auch immer, lies dir besser nochmal deinen Wiki-Artikel durch, das mit dem zur Laufzeit erzeugten, virtuellen Zeiger ist Unfug 😉



  • 314159265358979 schrieb:

    Du meinst wohl Gremlin.
    Wie auch immer, lies dir besser nochmal deinen Wiki-Artikel durch, das mit dem zur Laufzeit erzeugten, virtuellen Zeiger ist Unfug 😉

    Hast wohl recht...



  • Kann mir mal einer ein Beispiel nennen warum nicht schon zur Compilezeit bei einem Base Class Pointer bestimmen kann ob die Funktion aus der Base Class oder einer abgeleiteten Klasse verwendet werden soll. Der Compiler sieht doch welcher Typ uebergeben wird.

    void funktion(Base* ptr)
    {
         //do something
    }
    
    main()
    {
    // Der Compiler sollte doch erkennen dass eine abgeleitete KLasse uebergeben wird
    funktion (& DerivedClass ) ;
    }
    


  • blurry333 schrieb:

    Der Compiler sieht doch welcher Typ uebergeben wird.

    Wenn er die Funktion kompiliert, dann weiß der Compiler nur, dass ein Base* übergeben wird. Die Funktion könnte zur Laufzeit aus einer Bibliothek aus aufgerufen werden oder sonstwas, wo der Compiler nichtmal theoretisch den Quellcode des Aufrufs kennen könnte...

    Allerdings sind moderne Compiler sehr schlau und werden, wenn angebracht, entsprechende Optimierungen anwenden, wenn sie den Typ des übergebene Objektes zur Laufzeit bestimmen können. Das sind aber nur Optmierungen, die in manchen Fällen möglich sind und ändert nichts am Prinzip der Polymorphie...



  • blurry333 schrieb:

    Kann mir mal einer ein Beispiel nennen warum nicht schon zur Compilezeit bei einem Base Class Pointer bestimmen kann ob die Funktion aus der Base Class oder einer abgeleiteten Klasse verwendet werden soll.

    Zur Compilezeit steht aber nicht unbedingt fest, auf was der Zeiger zeigt. Die statische Typinformation ist nur: Zeiger auf Base. Deine Funktion kann man ja auch von einem anderen Modul aus aufrufen, das einen Zeiger auf wer-weiß-was übergibt. Polymorphie ist nicht kostenlos. Deswegen bekommst Du sie in C++ nur, wenn Du danach fragst. Und das Zauberwort heißt hier "virtual". Ohne virtual gibt es auch kein "Überschreiben" (overriding). Du fügst einfach eine neue Funktion hinzu, die die gleichnamige aus der Basisklasse nur "versteckt". Das ist unter dem Begriff "name hiding" bekannt. Die "alte" Funktion ist trotzdem noch aufrufbar:

    struct Base {
      void doSomething(); // deklariert Base::doSomething
    };
    
    struct Derived : Base {
      void doSomething(); // deklariert Derived::doSomething
    };
    
    Derived* p = ...;
    p->doSomething();       // Derived::doSomething
    p->Base::doSomething(); // Base::doSomething
    Base* q = p;
    q->doSomething();       // Base::doSomething
    

    Welche Funktion hier aufgerufen wird, regelt das "Name lookup". Das erste doSomething ist unqualifiziert. Der Compiler schaut erstmal in Derived nach. Falls es da nichts geben sollte, schaut er in Base nach. Aber da es in Derived auch ein doSomething gibt, hört er da schon mit der Suche auf. Zur Compilezeit steht hier also schon fest, welche Funktion aufgerufen wird. Möchtest Du das vom dynamischen Typ abhängig machen, benötigst Du virtuelle Funktionen. Die kriegst Du nur, wenn Du explizit danach "fragst".


Anmelden zum Antworten