Hilfe zu polymorphie Aufgabe



  • Hiho,

    Ich bin grad dabei alte Klausuren für kommende Informatik Klausur zu lösen. Doch bei einer Aufgabe kann ich mir das resultat im Compiler einfach nicht erklären.

    class A 
    { 
    protected: 
         string name; 
    public: 
         A(string name="NN") : name(name) {}; 
         virtual string getName() const 
         {    return "A::getName: name = " + name;   } 
         virtual void print(bool nl=true) const 
         { 
              if (nl) cout << "A::print - "; 
              cout << getName();    
              if (nl) cout << endl;              
         } 
    }; 
    
    class B : virtual public A  
    { 
         string b; 
    public: 
         B(string name, string b="B") : A(name), b(b) {}; 
         virtual void print(bool nl=true) const 
         { 
              if (nl) cout << "B::print - "; 
              A::print(false); 
              cout << ", b=" << b;  
              if (nl) cout << endl; 
         } 
    }; 
    
    class C : public B  
    {    string c; 
    public: 
         C(string name, string c="C", string b="B")  : B(name,b), c(c) {}; 
         string getName() const 
         {    return "C::getName: name = " + name;   } 
         virtual void print(bool nl=true) 
         { 
              if (nl) cout << "C::print - "; 
              B::print(false); 
              cout << ", c=" << c;  
              if (nl) cout << endl; 
         } 
    }; 
    
    int main() 
    { 
         C c("C-Obj");             
         C * cptr = &c;           
         ((A*)(cptr))->print();      //ruft print() aus Klasse B auf
         return 0;            
    }
    

    In der dritten Zeile der Main wird das Print() der Klasse B aufgerufen aber warum?
    Ich dachte der Cast davor ist egal weil eh in der Virtuellen Tabelle geschaut wird und dann das Print von C aufgerufen wird. Aber dem scheint nicht so zu sein 😞
    Dazu kommt noch das die Print Methoden von A und B const sind im Gegensatz zur Print von C. Da const zur Signatur zählt kann es doch überhaupt nicht sein, dass das Print von B aufgerufen wird. Ich bin verwirrt 😞

    MFG Fy



  • Fy schrieb:

    Dazu kommt noch das die Print Methoden von A und B const sind im Gegensatz zur Print von C. Da const zur Signatur zählt kann es doch überhaupt nicht sein, dass das Print von B aufgerufen wird. Ich bin verwirrt 😞

    Doch, genau das dürfte der Grund sein, warum die Methode von B aufgerufen wird. B::print() hat die selbe Signatur wie A::print() und wird deshalb virtuell aufgerufen, C::print() hat eine andere Signatur und gilt deshalb als eigenständige Funktion.



  • Das print von C ist ein anderes als das von A und B, wegen dem Fehlen von const .



  • Warum wird dann nicht das Print von A aufgerufen? Der Up-Cast geht ja auf A.
    Oder wird nur in die VTabelle geschaut und der Cast ignoriert? Aber wie kommt Die Tabelle dann auf B::print()?

    Dass das Objekt nicht const ist aber eine const Methode aufruft ist dann egal?



  • Fy schrieb:

    Warum wird dann nicht das Print von A aufgerufen? Der Up-Cast geht ja auf A.
    Oder wird nur in die VTabelle geschaut und der Cast ignoriert? Aber wie kommt Die Tabelle dann auf B::print()?

    Bei virtuellen Methoden wird die Version der Klasse aufgerufen, die sie als letztes in der Hierarchie überschrieben hat (anhand der vtable) - und das ist in deinem Fall B (der Cast sorgt nur dafür, daß die von C definierte Funktion nicht mehr zur Verfügung steht, die hat einen eigenen Eintrag in der vtable).

    PS: Klar darfst du für ein nicht-konstantes Objekt eine konstante Methode aufrufen.



  • CStoll schrieb:

    Fy schrieb:

    Warum wird dann nicht das Print von A aufgerufen? Der Up-Cast geht ja auf A.
    Oder wird nur in die VTabelle geschaut und der Cast ignoriert? Aber wie kommt Die Tabelle dann auf B::print()?

    Bei virtuellen Methoden wird die Version der Klasse aufgerufen, die sie als letztes in der Hierarchie überschrieben hat (anhand der vtable) - und das ist in deinem Fall B (der Cast sorgt nur dafür, daß die von C definierte Funktion nicht mehr zur Verfügung steht, die hat einen eigenen Eintrag in der vtable).

    PS: Klar darfst du für ein nicht-konstantes Objekt eine konstante Methode aufrufen.

    Ah jetzt hab ichs verstanden. Vielen Dank 🙂


Anmelden zum Antworten