virtuelle Funktionen und Vectoren



  • Ich habe folgendes Problem:

    #include <stdlib.h>
    #include <iostream.h>
    #include <vector>
    
    class cA
    {
    public:
    cA() {}
    virtual void draw() {cout<<"Draw:A"<<endl;}
    };
    
    class cB : public cA
    {
    public:
    cB() {}
    virtual void draw() {cout<<"Draw:B"<<endl;}
    };
    
    int main()
    {
    std::vector<cA> Liste;
    std::vector<cA>::Iterator it;
    
    cA testA;
    cB testB;
    
    Liste.push_back(testA);
    Liste.push_back(testB);
    
    it = Liste.begin();
    
    while(it != Liste.end())
    {
    it->draw();
    it++;
    }
    
    return 0;
    }
    

    Nun greift er aber immer auf die Draw-Funktion von cA zu, die Ausgabe ist also zweimal "Draw:A", obwohl die Funktion draw() als virtual deklariert ist. 😕

    Kann es sein dass der Vector dass ganze durcheinander bringt?



  • probiers mal mit

    std::vector<cA*> Liste;
    ...
    
    Liste.push_back(new testA);
    Liste.push_back(new testB);
    


  • Ne, tut er nicht. Der Vector ist in Ordnung.
    Du packst da aber eine Kopie von cB rein. Durch das Kopieren verliert Dein cB Objekt aber alle Besonderheit, die es cA hinzufügt und wird wieder ein reines cA Objekt (in ein cA-Objekt passt auch nur cA-Objekt rein).
    Du musst cA Pointer in dem Vektor ablegen, dann sollte das auch klappen:

    std::vector<cA*> Liste;
    //...
    Liste.push_back(&testA);
    Liste.push_back(&testB);
    //...
    


  • Danke euch beiden, hat funktioniert.



  • ist ein gängiges problem für anfänger

    nennt sich auch slicing falls du in der literatur mal nachlesen willst 🙂



  • inpimp schrieb:

    ist ein gängiges problem für anfänger

    nennt sich auch slicing falls du in der literatur mal nachlesen willst 🙂

    Genau.
    Du solltest auch darauf achten bei Klassen die nicht kopierbar sind auch den copy-ctor und den assignment-operator zu "sperren".
    Das machst du entweder indem du einen eigenen copy-ctor und assignment-operator als private deklarierst (definieren braucht du die beide nicht), oder indem du von einer Klasse ableitest die bereits auf diese Art nicht kopierbar gemacht wurde. Oder ein Member mit einer solchen nicht kopierbaren Klasse anlegst.


Anmelden zum Antworten