2016-04-29 4 views
0

Ich habe eine Warteschlange, die Objekte der Klasse Event enthält.Funktion Polymorphismus mit Referenz-Datentyp

std::priority_queue<Event> events; 

Aber Ereignis ist nur eine Oberklasse von tatsächlichen Ereignissen. Nehmen wir an, wir folgende Klassen:

class Event{ 
    public: 
    void Action(){ 
     std::cout<<"do nothing"<<std::endl; 
    } 
}; 

class XEvent : public Event{ 
    public: 
    void Action(){ 
      std::cout<<"do x"<<std::endl; 
    } 

class YEvent : public Event{ 
    public: 
    void Action(){ 
      std::cout<<"do y"<<std::endl; 
    } 
}; 

und in der Hauptfunktion:

int main(){ 
    std::vector<Event> events; 
    events.push_back(XEvent x); 
    events.push_back(YEvent y); 
    Event e = events[0]; 
    e.Action(); 
} 

Ich möchte e.Action nach überschriebene Version verhalten. (d. H. "Mache x").

Aber stattdessen gibt mir die Ausgabe "nichts tun". Irgendwelche Vorschläge?

p.s. Ich suche tatsächlich nach einer Möglichkeit, dies zu tun, ohne Zeiger zu verwenden

+0

Lesen Sie mehr über Aufschneiden. Der Vektor sollte 'std :: vector > Ereignisse sein;' eher. –

Antwort

0

Das Einfügen in den Vektor kopiert das Element. Der Zieltyp ist immer Event, der der Vorlage als Parameter zugewiesen wird. Dadurch wird der Typ geändert.

Vorschläge:

  • Verwenden Sie einen std::function statt. Dies kann genau das sein, nach dem Sie suchen, um Ereignisse zu verarbeiten.
  • Verwenden Sie stattdessen einen (intelligenten) Zeigertyp, sodass Sie polymorphe Elemente speichern können.
  • Verwenden Sie stattdessen einen Smart Union/Variant-Typ, z. Boost.Any oder Boost.Variant (nicht sicher, ob einer von beiden inzwischen standardisiert ist).
0
class Event{ 
    public: 
    virtual void Action(){ 
     std::cout<<"do nothing"<<std::endl; 
    } 
}; 

Verwendung virtuelle Funktion wie oben, aber Sie ein Objekt erstellt, dass von Klasse Event sein können Sie einen Zeiger erstellen sollten;

int main(){ 
    std::vector<Event> events; 
    events.push_back(XEvent x); 
    events.push_back(YEvent y); 
    XEvent xe = events[0]; 
    Event* e = &xe; 
    e->Action(); 
} 

oder implementieren Sie ein Objrct.

+0

Das Problem mit dieser Lösung ist, dass ich im Allgemeinen nicht weiß, welche Art von Ereignisereignissen [i] sein wird, also kann ich XEvent xe = events [i] nicht tun; – finaleblue

+0

Verwenden Sie Cast-Operator wie Event * e = static_cast xe – CMLDMR

0

Verwendung intelligenter Zeiger gemeinsamen Zeiger, versuchen fallowing Code:

#include<iostream> 
#include<vector> 
#include <memory> 

class Event{ 
    public: 
    virtual void Action(){ 
     std::cout<<"do nothing"<<std::endl; 
    } 
}; 

class XEvent : public Event{ 
    public: 
    void Action(){ 
      std::cout<<"do x"<<std::endl; 
    } 
}; 

class YEvent : public Event{ 
    public: 
    void Action(){ 
      std::cout<<"do y"<<std::endl; 
    } 
}; 
int main(){ 
    std::vector<std::shared_ptr<Event>> events; 
    events.push_back(std::make_shared<XEvent>()); 
    events.push_back(std::make_shared<YEvent>()); 
    std::shared_ptr<Event> e = events[0]; 
    e->Action(); 
    return 0; 
}