Funktion mit unbekanntem Rückgabetyp



  • randomClass als Parameter auch nur CEinheit* nehmen lassen.
    Denn auch wenn du virtuelle Funktionen hast, heißt das noch nicht dass du einfach ein CEinheit* übergeben kannst, wo ein CRitter* erwartet wird.



  • Ah es funktioniert, danke euch. 🙂



  • Ich habe wieder ein kleines Problem... und zwar möchte ich, dass der Spieler zwischen drei verschiedenen Klassen wählen kann.

    Basisklasse:
    CEinheit

    abgeleitete Klassen:
    CKrieger
    CMagier
    CBogenschütze

    Wie kriege ich es jetzt hin, dass ich einen Spieler habe, der zur Laufzeit seine Klasse aussucht und mit dieser dann das ganze Spiel über spielen kann? Ich hab an eine Klasse CSpieler gedacht, die über eine Funktion GetClass oder so ihre Klasse annimmt, allerdings weiß ich nicht was ich für einen Parameter nehmen soll. Wie würdet ihr das lösen?



  • class Klasse
    {
    };
    
    class Ritter : public Klasse
    {
    };
    
    int main ()
    {
        Klasse* k = new Ritter;
    }
    


  • Dann habe ich aber ja das Problem, dass k keine speziellen Funktionen von Ritter aufrufen kann, sondern nur die von Klasse. Der Ritter soll ja Memberfunktionen haben, also Attacken, die ihn von den anderen unterscheiden.



  • Kay schrieb:

    Dann habe ich aber ja das Problem, dass k keine speziellen Funktionen von Ritter aufrufen kann, sondern nur die von Klasse. Der Ritter soll ja Memberfunktionen haben, also Attacken, die ihn von den anderen unterscheiden.

    Das ist ein Designfehler von dir. Überleg wie man es besser machen könnte, mit virtuellen Funktionen.



  • So... Hab jetzt mal pure virtuelle Funktionen eingebaut. Jetzt werden die richtigen Funktionen aufgerufen, aber ich habe immernoch keinen Zugriff auf die Member von CRitter zum Beispiel. Wie soll ich das da machen?

    #include <iostream>
    
    using namespace std;
    
    class CEinheit // pure virtuelle Basisklasse
    {
    	protected:
    		int m_Lebenspunkte; // hat jeder Charakter
    
    	public:
    
    		CEinheit ()
    		{
    			m_Lebenspunkte = 0;
    
    		}
    
    		virtual ~CEinheit () {cout << "Destruktor Basisklasse\n";}
    
    		virtual void Angriff1  () = 0;
    		virtual void Angriff2  () = 0;
    		virtual void Angriff3  () = 0;
    
    };
    
    class CBogenschütze : public CEinheit
    {
    	private:
    		int m_Power; // Haben nur Bogenschützen
    
    	public:
    		CBogenschütze ()
    		{
    			m_Power = 60;
    
    		};
    
    		~CBogenschütze () {cout << "Destruktor Bogenschützer\n";}
    
    		void Angriff1  () {cout << "Zing!\n";}
    		void Angriff2  () {cout << "Zang!\n";}
    		void Angriff3  () {cout << "Zong!\n";}
    
    };
    
    class CRitter : public CEinheit
    {
    	private:
    		int m_Kraft; // Haben nur Ritter
    
    	public:
    		CRitter ()
    		{
    			m_Kraft = 40;
    			cout << "Neuer Ritter erstellt" << endl;
    		};
    
    		~CRitter () {cout << "Destruktor Ritter\n";}
    
    		void Angriff1  () {cout << "Boom!\n";}
    		void Angriff2  () {cout << "Bamm!\n";}
    		void Angriff3  () {cout << "Bang!\n";}
    
    };
    
    int main ()
    {
    	CRitter *pRitter = NULL;
    	pRitter = new CRitter;
    	pRitter->Angriff1(); // funzt super
    
    	CBogenschütze *pBogenschütze = NULL;
    	pBogenschütze = new CBogenschütze;
    	pBogenschütze->Angriff2(); // funzt super
    
    	CEinheit *pSpieler = NULL;
    	pSpieler = new CRitter; // Spieler soll ein Ritter sein
    	pSpieler->Angriff1(); // funzt, ruft Attacke von Ritter auf
    
    	system("pause");
    	return 0;
    }
    


  • Wunderbar! Einfach soweit abstrahieren dass bei der Verwendung einer Einheit-Instanz nicht mehr von Belang ist, was das jetzt konkret ist.
    Anstelle von Angriff1, Angriff2, use kannst du dir überlegen, der Einheit noch eine Methode "int anzahlAngriffe()" zu geben, und die Angriff-Methode nach "void Angriff( int nummer )" umzubenennen.

    Du könntest aber auch mal ganz konkret beschreiben, warum du jetzt unbedingt Zugriff auf einen Ritter brauchst. Das würde wahrscheinlich mehr helfen das Problem zu lösen.



  • Also:

    Ich möchte ein Spiel schreiben, bei dem der Spieler gegen einen Computer Gegner kämpft. Wenn er den Ritter wählt, hat er ja andere Attacken als ein Magier zum Beispiel, deswegen ist es so wichtig, dass er ein Ritter bleibt, aber das geht ja jetzt so mit den puren virtuellen Funktionen anscheinend.

    Das Problem ist nur die Membervariablen, wie kann ich es anstellen, dass der Ritter auf seine Membervariable m_Kraft zugreifen kann, sprich pSpieler->m_Kraft (davon abgesehen dass es so eh nicht geht weil es private ist).

    Diese Membervariablen sind deswegen wichtig, weil ein Bogenschütze Power und nicht Kraft hat, sonst würde ich die ja einfach in die Basisklasse packen. Oder würde man einfach hingehen und anstatt Mana, Power, Kraft, einfach eine Variable namens Ressource machen? Die kann ich ja dann in die Basisklasse packen.



  • Ich verstehe den Unterschied zwischen Power und Kraft nicht 😃
    http://www.dict.cc/englisch-deutsch/power.html
    Ich würde wohl ein universelles Wort nehmen, denn sogesehen hat am Ende jede Klasse irgendwie eine "Energie".
    Außerdem finde ich Attacken in die Klassen Klasse zu schreiben für wenig sinnvoll, dafür ist eine Spell oder Skill Klasse gedacht.



  • Kay schrieb:

    Diese Membervariablen sind deswegen wichtig, weil ein Bogenschütze Power und nicht Kraft hat, sonst würde ich die ja einfach in die Basisklasse packen. Oder würde man einfach hingehen und anstatt Mana, Power, Kraft, einfach eine Variable namens Ressource machen? Die kann ich ja dann in die Basisklasse packen.

    Es sollte egal sein, was du vor dir hast! Es sollte dich nicht interessieren, ob das jetzt ein Bogenschütze mit "Power" oder ein Ritter mit "Kraft" ist.
    Deine virtuellen Funktionen kümmern sich darum, was im Hintergrund passiert.
    Du hast die Funktion "Einheit::attack(Einheit* opponent)", z.B.
    Oder von mir aus kapsele die einzelnen Arten von Attacken noch mal in eigenen Klassen.
    Es liegt jetzt an dir zu entscheiden, was ein Angriff dann bewirkt. Ein Schlag mit dem Schert auf den Kopf des Gegners könnte nun einen bestimmten Schaden zufügen. Oder gleich den Kopf abtrennen, wenn du keine adäquate Verteidung oder Rüstung aufweisen kannst. Das Ganze ist natürlich ETWAS komplexer als ein simples cout.

    Also löse dich von der Vorstellung, auf ein Objekt speziell reagieren zu wollen, sondern gib deiner CEinheit ein Interface, das im Allgemeinen Sinne die einzelnen Interaktionen zulässt.



  • Ok, ich programmier mal ein bisschen weiter und poste dann nochmal das Ergebnis, danke euch. 🙂


Anmelden zum Antworten