Polymorphie funktioniert nicht
-
Hallo,
ich habe wieder ein Problem. Ich erstelle gerade ein Konsolenbasiertes Monopoly.
Dazu habe ich eine "abstrakte" Klasse MFeld, eine Klasse "KaufbaresFeld" für kaufbare Felder die von MFeld erbt und jeweils eine Klasse für die verschiedenen Aktionsfelder die auch von MFeld erben.In der Klasse MFeld habe ich eine virtuelle Methode void tueFeld(...), die ich in den erbenden Klassen überschreibe. Nun erstelle ich in meinem Programm einen Vektor von MFeld wo ich verscheidene kaufbare Felder und Aktionsfelder einfüge. Später hole ich mir ein Element aus dem Vektor raus und rufe tueFeld(...) auf. Das Problem ist, dass er dann immer in die Methode von MFeld reingeht, anstatt in die überschreibende Methode der erbenden Klasse.
Die Klasse MFeld:
#pragma once #include <string> #include "Spieler.h" #include "Monopoly.h" class Monopoly; class MFeld{ protected: int iPosition; bool bIsKaufbar; std::string sBeschreibung; public: MFeld(int iPosition, bool bIsKaufbar, std::string sBeschreibung); ~MFeld(void); std::string getBeschreibung(); virtual void tueFeld(Spieler oSpieler, Monopoly oMonopoly); int getPosition(); };#include "StdAfx.h" #include "MFeld.h" MFeld::MFeld(int iPosition, bool bIsKaufbar, std::string sBeschreibung): iPosition(iPosition), sBeschreibung(sBeschreibung), bIsKaufbar(bIsKaufbar){ } MFeld::~MFeld(void){ } std::string MFeld::getBeschreibung(){ return this->sBeschreibung; } int MFeld::getPosition(){ return this->iPosition; } void MFeld::tueFeld(Spieler oSpieler, Monopoly oMonopoly){ }Meine Felder baue ich dann so zusammen und füge es in einen Vector:
vFelder.push_back(StartFeld(1)); vFelder.push_back(KaufbaresFeld(2, "FH Caféteria (Kaufpreis = 1 Mio €, Mieteinnahmen = 100.000 €)", 100000, 1000000, Spieler("N/A"))); vFelder.push_back(LanFeld(3)); vFelder.push_back(KaufbaresFeld(4, "FH Mensa (Kaufpreis = 2 Mio €, Mieteinnahmen = 200.000€)", 200000, 2000000, Spieler("N/A"))); vFelder.push_back(JackpotFeld(5)); vFelder.push_back(KaufbaresFeld(6, "Ferggis (Kaufpreis = 4 Mio €, Mieteinnahmen = 400.000€)", 400000, 4000000, Spieler("N/A"))); vFelder.push_back(ZurLanFeld(7)); vFelder.push_back(KaufbaresFeld(8, "Big Box Allgäu (Kaufpreis = 8 Mio €, Mieteinnahmen = 800.000€)", 800000, 8000000, Spieler("N/A")));Im Verlauf des Spieles passiert dann das: Ich bestimme die Position des Spielers und führe dann das Feld aus. Leider geht er hier immer in die virtuelle Methode von MFeld rein. Auch wenn das Objekt eigentlich vom Typ KaufbaresFeld ist.
vFelder.at(oSpieler.getPosition()-1).tueFeld(oSpieler, *this);Hier noch der Code vom kaufbaren Feld:
#pragma once #include "MFeld.h" #include <string> #include "Spieler.h" #include "Monopoly.h" class KaufbaresFeld : public MFeld{ private: bool bRenoviert; int iMietPreis; int iKaufPreis; Spieler oBesitzer; public: KaufbaresFeld(int iPosition, std::string sBeschreibung, int iMietPreis, int iKaufPreis, Spieler oBesitzer); ~KaufbaresFeld(void); void tueFeld(Spieler oSpieler, Monopoly oMonopoly); void setRenoviert(bool bRenoviert); void setBesitzer(Spieler oBesitzer); };#include "StdAfx.h" #include "KaufbaresFeld.h" KaufbaresFeld::KaufbaresFeld(int iPosition, std::string sBeschreibung, int iMietPreis, int iKaufPreis, Spieler oBesitzer): MFeld(iPosition, true, sBeschreibung){ this->iMietPreis = iMietPreis; this->iKaufPreis = iKaufPreis; this->oBesitzer = oBesitzer; this->bRenoviert = false; } KaufbaresFeld::~KaufbaresFeld(void) { } void KaufbaresFeld::setBesitzer(Spieler oBesitzer){ this->oBesitzer = oBesitzer; } void KaufbaresFeld::setRenoviert(bool bRenoviert){ this->bRenoviert = bRenoviert; } void KaufbaresFeld::tueFeld(Spieler oSpieler, Monopoly oMonopoly){ char cEingabe; int iGesamtMietPreis; printf(this->sBeschreibung.c_str()); printf("\n"); if (this->oBesitzer.getName() == "N/A"){ printf("Möchten Sie kaufen? 'y' für Ja eingeben\n"); cEingabe = getchar(); if (cEingabe == 'y'){ oSpieler.setGeld(oSpieler.getGeld() - 1000000); this->oBesitzer = oSpieler; } }else if(this->oBesitzer.getName() == oSpieler.getName()){ printf("Das Feld gehört Ihnen bereits. Möchten Sie für %d renovieren? Für Ja 'y' eingeben\n", this->iKaufPreis); cEingabe = getchar(); if (cEingabe == 'Y'){ printf("Es wird renoviert und das Geld abgezogen\n"); } }else{ if (this->bRenoviert == true){ iGesamtMietPreis = this->iMietPreis + this->iMietPreis * 0.1f; }else{ iGesamtMietPreis = this->iMietPreis; } printf("Das Feld gehört bereits %s. Die Miete von %d wird transferiert", this->oBesitzer.getName().c_str(), this->iMietPreis); //Wenn Spieler B nur noch 50 hat aber die Miete 100 ist? Bzw. Mit Schuldengrenze oSpieler.setGeld(oSpieler.getGeld() - this->iMietPreis); this->oBesitzer.setGeld(this->oBesitzer.getGeld() + this->iMietPreis); } }Habe ich einen Fehler eingebaut, oder erkennt c++ generell nicht von welchem Typ das Objekt tatsächlich ist?
Gruß hyperion
-
vFelder ist so definiert, gell?
vecctor <MFeld> vFelder;Wenn du ein push_back machst, wird das, das du übergibst, kopiert. So, und was passiert wohl wenn du ein KaufbaresFeld übergibst? Das sozusagen:
KaufbaresFeld kf; Myfeld mf = kf;Es wird nur der Myfeld-Teil von KaufbaresFeld kopiert. Nun dürfte auch klar sein, wieso immer Myfeld::tueFeld aufgerufen wird. Das Ganze hat also nichts mit Polymorphie zu tun...
-
Danke. Gibt es auch eine Möglichkeit in c++ das ohne Zeiger zu lösen?
Gruß hyperion
-
hyperion1 schrieb:
Danke. Gibt es auch eine Möglichkeit in c++ das ohne Zeiger zu lösen?
Nein :p Der Datentyp eines Objekts ist ja fix.
-
Um es anders auszudrücken: Polymorphie funktioniert bei Containern (z.B. std::vector<>) nur mit Zeigern (bzw. Shared-Pointern).
-
Th69 schrieb:
Um es anders auszudrücken: Polymorphie funktioniert bei Containern (z.B. std::vector<>) nur mit Zeigern (bzw. Shared-Pointern).
bei Containern? Für ein polymorphes Verhalten brauchst du doch immer einen Zeiger/Referenz.
-
Gugelmoser schrieb:
Th69 schrieb:
Um es anders auszudrücken: Polymorphie funktioniert bei Containern (z.B. std::vector<>) nur mit Zeigern (bzw. Shared-Pointern).
bei Containern? Für ein polymorphes Verhalten brauchst du doch immer einen Zeiger/Referenz.Pack doch dann mal Referenzen in Container

-
Sägebart schrieb:
Gugelmoser schrieb:
Th69 schrieb:
Um es anders auszudrücken: Polymorphie funktioniert bei Containern (z.B. std::vector<>) nur mit Zeigern (bzw. Shared-Pointern).
bei Containern? Für ein polymorphes Verhalten brauchst du doch immer einen Zeiger/Referenz.Pack doch dann mal Referenzen in Container

Geht nücht, Referenzen sind keine Objekte.
-
Frage am Rande...
hyperion1 schrieb:
class MFeld{ protected: int iPosition; bool bIsKaufbar; std::string sBeschreibung; public: MFeld(int iPosition, bool bIsKaufbar, std::string sBeschreibung); ~MFeld(void); std::string getBeschreibung(); virtual void tueFeld(Spieler oSpieler, Monopoly oMonopoly); int getPosition(); };Warum deklarierst Du überhaupt den Destruktor? Das kannst Du doch komplett dem Compiler überlassen...