Virtuelle Klassen in Vector
-
Hallo,
wenn ich in meinen vector<Auftraege*> einen BauAuftrag über die Funktion AuftragHinzu() hinzufügen will, und dann darauf zugreifen will kommt ein Fehler:class Auftrag{ private: enum status{FERTIG, IN BEARBEITUNG,...}; int x,y,z; time_t start; //Wann der Auftrag ausgeführt werden soll int status; public: Auftrag(int status, time_t start){ this->status=status; this->start=start; } ~Auftrag(); virtual string Bauen(void)=0; }; class Bauauftrag:Auftrag{ private: int gebaeude; enum gebaeude_{TURM,BRUECKE,WERKSTATT,HAUS}; public: Bauauftrag(int status, int gebaeude):Auftrag(status); ~Bauauftrag(); virtual string Bauen(void); }; [...] vector<Auftrag*> Auftraege; [...] void AuftragHinzu(Bauauftrag tasktoadd){ task *ptr; ptr = &tasktoadd; this->Auftraege.insert(this->Auftraege.end(),ptr); } int main(void){ task *ptr; Bauauftrag Eisenschmiede (...); ptr = &Eisenschmiede; Auftraege.insert(Auftraege.end(),ptr); cout << account.Auftraege[0]->Bauen(); //Funktioniert AuftragHinzu(Eisenschmiede); //Alternativemöglichkeit cout << Auftraege[0]->Bauen(); //Fehler: //pure virtual method called terminate called without an active exception }Dem Fehler zufolge wird die virtuelle Methode von Auftrag ausgeführt und nicht die von Bauauftrag... wenn ich die Funktion AuftragHinzu() einfach in die main Methode kopiere, wird dann doch das Bauen() von Bauauftrag ausgeführt... wie kann das sein?

Danke für Hilfe
-
Die Einrückung ist ja grauenhaft! Mach das bitte nochmal ordentlich, dass man auch was erkennt.
Ansonsten solltest du dich nochmal mit Gültigkeit von Objekten (wie lange leben sie? Wann wird kopiert? ...) beschäftigen und folgende Funktion genauer untersuchen:void AuftragHinzu(Bauauftrag tasktoadd){ task *ptr; ptr = &tasktoadd; this->Auftraege.insert(this->Auftraege.end(),ptr); }
-
Neben dem was l'abra d'or gesagt hat, vor allem wegen der Einrückung, möchte ich noch die folgenden Dinge anmerken:
1. Verzichte auf globale Variablen.
2.voidbei Funktionen ohne Parametern ist in C++ eher unüblich.
3. Schau dir mal die Schnittstelle vonstd::vectoran, wenn du den Container schon verwendest. Zum Beispielpush_backundfrontsind Funktionen, welche du benutzen könntest, anstatt deine "Workarounds".Grüssli
-
Sry für den Code
Hier nochmal ordentlich eingerückt und verbessert:class Auftrag{ private: enum status{FERTIG, IN BEARBEITUNG,...}; int x,y,z; time_t start; //Wann der Auftrag ausgeführt werden soll int status; public: Auftrag(int status, time_t start){ this->status=status; this->start=start; } ~Auftrag(); virtual string Bauen(void)=0; }; class Bauauftrag:Auftrag{ private: int gebaeude; enum gebaeude_{TURM,BRUECKE,WERKSTATT,HAUS}; public: Bauauftrag(int status, int gebaeude):Auftrag(status); ~Bauauftrag(); virtual string Bauen(void); }; [...] vector<Auftrag> Auftraege; [...] int main(){ Auftrag *ptr; Bauauftrag Eisenschmiede (...); ptr = &Eisenschmiede; Auftraege.push_back(ptr); cout << Auftraege.front()->Bauen(); }Danke nochmal

-
Bauen() wird verwendet, aber nirgends definiert.
Die Art und Weise wie du den Bauauftrag zu der Auftragsliste hinzufügst ist sehr ungewöhnlich. Was spricht gegen das hier?
Auftraege.push_back(new Bauauftrag());Was ist task?
-
SeppJ schrieb:
Bauen() wird verwendet, aber nirgends definiert.
Versteh ich nicht... in Zeile 13 und 22 definiere ich es doch?!
SeppJ schrieb:
Die Art und Weise wie du den Bauauftrag zu der Auftragsliste hinzufügst ist sehr ungewöhnlich. Was spricht gegen das hier?
Auftraege.push_back(new Bauauftrag());Hm ich habs jetzt so gemacht:
int main(){ Bauauftrag Eisenschmiede (...); Auftraege.push_back(&Eisenschmiede); cout << Auftraege.front()->Bauen(); }Ich finde das aber auch unschön, weil im Vector nur die Zeiger auf die Objekte gespeichert werden... Hat jemand eine Idee wie man das besser lösen kann?
SeppJ schrieb:
Was ist task?
Hab ich falsch abgeschrieben, im Orginalcode heißt die Klasse Auftrag task.

-
[MOP] schrieb:
Ich finde das aber auch unschön, weil im Vector nur die Zeiger auf die Objekte gespeichert werden... Hat jemand eine Idee wie man das besser lösen kann?
Wenn du polymorphes Verhalten möchtest, kommst du nicht um Zeiger herum. Allerdings gibt es für besitzende Zeiger Alternativen wie Boosts Pointer-Container, das nur so als Anmerkung.
Mit
Auftraege.push_back(&Eisenschmiede);referenzierst du die Eisenschmiede nur. Das ist völlig okay, solange du dafür sorgst, dass du nicht auf ungültige Zeiger zugreifst (automatische Objekte werden am Ende des Scopes zerstört).
-
Der Destruktor sollte auch virtual sein. Sonst wirst du Probleme bekommmen, sobald du die Objekte dynamisch allozierst.