[GELÖST] (Anfänger) ohne includierung Code implementieren?



  • Schönen guten Abend miteinander!

    Ich bin gerade dabei ein "kleines" Spiel zu programmieren und finde für ein - ich denke mal einfaches - Problem keine Lösung. Es handelt sich um ein Spiel bei dem man momentan nur im Menue zwischen 2 Champions die man spielen möchte auswählen kann. Es gibt für jeden Champion eine extra Datei und jeder Champion erbt von einem Champion-Grundgerüst. Dieses Grundgerüst muss logischerweise in jeder Champion-Datei included werden damit es funktioniert:

    #include "ArenaChampion.cpp"
    
    class Schlaechter : public Champion
    {
    

    und

    #include "ArenaChampion.cpp"
    
    class Schattenwanderer : public Champion
    {
    

    Nun muss ich die jeweiligen Klassen "Schlaechter" und "Schattenwanderer" in meiner Main-Datei includen damit ich Instanzen von ihnen erstellen kann. Dann fängt der Compiler allerdings an zu fauchen und sagt mir die Klasse Champion wurde bereits definiert, was ich auch verstehe, durch das includen der beiden Dateien wird zweimal die "ArenaChampion.cpp" includiert. Nur weiss ich leider keine Lösung für das Problem außer die Champions nicht in Dateien zu seperieren sondern in die ArenaChampion.cpp einzufügen. Das finde ich allerdings sehr unschön und meine Idee die Championklasse eine abstrakte zu machen würde dann auch nicht mehr funktionieren...

    Ich danke schonmal im vorfeld für alle die sich die Mühe machen mir zu helfen (:

    Mfg,
    Levyeme



  • Ops, ich habe vergessen noch die includierungen der Main-Datei hinzuzufügen:

    #include <iostream>
    #include <windows.h>
    #include <stdio.h>
    #include <string>
    #include "Schlaechter.cpp"
    #include "Schattenwanderer.cpp"
    //#include "ArenaChampion.cpp"
    
    using namespace std;
    
    int main()
    {
    


  • Warum inkludierst Du Source-(.cpp-) Files? Hast Du denn nicht brav Deklaration von Definition/Implementierung getrennt?

    @levyeme sagte in (Anfänger) ohne includierung Code implementieren?:

    [...] Dann fängt der Compiler allerdings an zu fauchen und sagt mir die Klasse Champion wurde bereits definiert, was ich auch verstehe, durch das includen der beiden Dateien wird zweimal die "ArenaChampion.cpp" includiert. Nur weiss ich leider keine Lösung für das Problem [...]

    Guckst Du: Include Guard.

    PS: <stdio.h> heißt in C++ <cstdio> und die Funktionen liegen im Namensraum std.



  • Mach für jede Klasse eine .h und eine .cpp-Datei.

    Die .h-Datei

    • muss einen Include-Guard bekommen
    • enthält niemals ein "using namespace ..."
    • enthält die Definition der Klasse ohne Implementierung
      • Ausnahme: Templates und inline-Funktionen

    Die .cpp-Datei

    • includet als allererstes ihre entsprechende .h-Datei (nach diesem Include am besten eine Leerzeile, dann sortieren dir viele Code-Formatter das auch nicht um)
    • enthält die Implementierung aller Funktionen, die nicht in der .h implementiert sind (d.h. alles, was nicht inline oder nicht template ist)

    Wichtig: es werden niemals .cpp-Dateien includet, sondern immer nur die .h-Dateien!

    Der Compiler kompiliert und linkt dann alle .cpp-Dateien - die .h-Dateien werden über die includes in den cpp mitkompiliert.

    Viel Erfolg bei Schlächten des Schattenwanderers 😉



  • Vielen Dank für die schnelle Antwort (:

    Ich hatte heute etwas Zeit und habe das mal ausprobiert. Alle .cpp's haben jetzt auch ne zugehörige .h Datei. Leider spuckt mir der Compiler jetzt was für mich ganz unverständliches aus. unzwar meint er: "string" does not name a type". Diese Meldung erscheint für alle Strings die ich deklariert habe. Hier die ganze ArenaChampion.h, wo bei "string champName" auch der erste der vielen String-Fehler rot markiert wird:

    /*
    	______________
    	BESCHREIBUNG
    	______________
    	
    	Dies ist die Champion-Datei für das Grundbaugerüst eines 
    	Characters/Champions, um das hinzufügen von weiteren Champions übersichtlicher
    	zu gestalten.!
    	
    */
    #ifndef ARENACHAMPION_H
    #define ARENACHAMPION_H
    
    #include <string>
    
    class Champion
    {
    	private:
    			
    		//HAUPTWERTE:
    			string champName;
    			int hp;
    			int stamina;
    			int staminaReg;
    			int dmg;
    			int armor;
    			
    			//Fähigkeiten Namen
    			string abillityNameOne;
    			string abillityNameTwo;
    			string abillityNameThree;
    			string abillityNameFour;
    			string abillityNameFive;
    			//Fähigkeiten Beschreibungen
    			string abillityDescOne;
    			string abillityDescTwo;
    			string abillityDescThree;
    			string abillityDescFour;
    			string abillityDescFive;
    			
    		//ZUSATZWERTE:
    			int extraDmg;  		//Poison, Fire etc.
    			bool frozen;	//Frozen etc.
    			
    			
    	public:
    		//
    		//	IDEEN:
    		//	
    		//
    			
    			
    			
    		//
    		//	____________
    		//	CONSTRUCTOR
    		//	____________
    		//
    			Champion();
    		//
    		//	___________________
    		//	ENDE - CONSTRUCTOR
    		//	___________________
    		//
    
    
    
    
    		//
    		//	____________________
    		//	VIRTUAL FÄHIGKEITEN
    		//	____________________
    		//
    			virtual void abillityOne(Champion *feind);
    			virtual void abillityTwo(Champion *feind);
    			//void abillityThree();
    			//void abillityFour();
    			//void abillityFive();
    		//
    		//	___________________
    		//	ENDE - FÄHIGKEITEN
    		//	___________________
    		//
    		
    		
    		
    		
    		//
    		//	___________
    		//	FUNKTIONEN
    		//	___________
    		//
    			//Champion verliert Leben
    			void loseHealth(int damage);
    			//Champion wird geheilt
    			void heal(int heal);
    			
    			//Hat der Champion Extraschaden durch Feuer, Gift etc. ?
    			bool hasExtras();
    			
    			//Champion einfrieren
    			void freeze();
    			//Champion auftauen
    			void defreeze();
    			//Ist der Champion gerade Handlungsunfähig?
    			bool isFrozen();
    		//
    		//	__________________
    		//	ENDE - FUNKTIONEN
    		//	__________________
    		//
    		
    		
    		
    
    		//
    		//	__________________
    		//	GETTER UND SETTER
    		//	__________________
    		//
    			//Setter
    			void setName(string nameSet);
    			void setHP(int hp);
    			void setStamina(int stamina);
    			void setStaminaReg(int staminaReg);
    			void setDmg(int dmg);
    			void setArmor(int armor);
    			void setExtraDmg(int extraDmg);
    			void setFrozen(bool isfrozen);
    			//Setter für Fähigkeitennamen und Beschreibung
    			void setAbillityOneName(string abiName);
    			void setAbillityTwoName(string abiName);
    			void setAbillityThreeName(string abiName);
    			void setAbillityFourName(string abiName);
    			void setAbillityFiveName(string abiName);
    			//
    			void setAbillityOneDesc(string abiDesc);
    			void setAbillityTwoDesc(string abiDesc);
    			void setAbillityThreeDesc(string abiDesc);
    			void setAbillityFourDesc(string abiDesc);
    			void setAbillityFiveDesc(string abiDesc);
    			
    			//Getter
    			string getName();
    			int getHP();
    			int getStamina();
    			int getStaminaReg();
    			int getDmg();
    			int getArmor();
    			int getExtraDmg();
    			//Getter für die Fähigkeiten Namen
    			string getAbillityOneName();
    			string getAbillityTwoName();
    			string getAbillityThreeName();
    			string getAbillityFourName();
    			string getAbillityFiveName();
    			//
    			string getAbillityOneDesc();
    			string getAbillityTwoDesc();
    			string getAbillityThreeDesc();
    			string getAbillityFourDesc();
    			string getAbillityFiveDesc();
    		//
    		//	_________________________
    		//	ENDE - GETTER UND SETTER
    		//	_________________________
    		//
    };
    
    #endif
    

    Ich habe leider nicht den blassesten schimmer im Moment. Leider habe ich gerade auch nicht viel Zeit um herumzuprobieren, wobei ich nicht wüsste wo ich anfangen sollte. Ich würde sonst die strings vielleicht durch char-Arrays ersetzen, aber damit löse ich das Problem ja eigentlich nicht sondern umgehe es...

    Einen schönen Abend wünsche ich euch noch (:



  • string liegt im Namensraum std, also schreibe std::string.

    @levyeme sagte in (Anfänger) ohne includierung Code implementieren?:

    One, Two, Three, Four; Five

    Arrays sind auch toll.



  • Das h/cpp Problem wurde ja erörtert. Ich wollte nur noch anmerken, das ich dieses Design ziemlich unsinnig finde. Ich würde meine Champions nicht alle voneinander ableiten. Ich würde einem Champion einen Vektor mit Adressen von Eigenschaften geben, wobei diese Eigenschaften dann von einer gemeinsamen Basisklasse ableiten. In einer Konfigurationsdatei würde ich dann steuern welcher Champion welche Eigenschaft mit evtl. welchen Einstellungen hat. Einige Eigenschaften haben vlt. alle, z.B. Hitpoints oder Inventory, andere vlt. nicht wie Zaubern oder Schleichen.



  • Super danke, dass hat die ganzen String-Fehler behoben (:

    Ich bin echt noch nicht weit mit meinem Programm/Spiel allerdings bin ich schon auf etliche Fehler gestoßen die ich eigenständig lösen konnte. Aber manchmal sind es die einfachsten Dinge die ich nicht bemerke ...

    Naja zum letzten Fehler und gleichzeitig zu einer Frage:
    Unzwar meckert der Compiler nun die Klasse Champion der .cpp-Datei wurde bereits definiert und kann nicht wieder definiert werden, dass verstehe ich soweit auch. Ich bin mir nur nicht ganz sicher ob ich den Fehler richtig sehe. Das bedeutet ja das in der Header-Datei bereits die Klasse definiert wird und folglich müsste ich ja die Klasse dann in der .cpp-Datei löschen, damit die Klasse nicht 2 mal definiert wird. Ich weiß allerdings dass das nicht geht also stehe ich gerade wieder auf dem Schlauch. Ich weiß ich habe mir da ein etwas komplexes Projekt ausgesucht wobei ich erst vor 5 Monaten angefangen habe und circa 5std pro Woche nur programmieren kann, aber ich bin sehr verbissen was das angeht und hätte zumindest gerne eine kleine, unfertige Version, in der man wenigstens etwas machen kann außer sich einen Champion auszusuchen, bevor ich dann mein nächstes, dafür kleineres Projekt starte.

    Zu TGGC:
    Ich kenne mich noch nicht mit Vektoren aus aber ich werde dies im Hinterkopf behalten und mit der Zeit mal bearbeiten, danke für den Tipp (:



  • @levyeme

    Ich weiß allerdings dass das nicht geht

    Aha. Warum?



  • Naja weil der Compiler dann nichts mit den private: und public: funktionen und variablen anzufangen weiss. Die genaue Fehlermeldung kann ich heute Abend nochmal reinschreiben 🙂



  • @levyeme Tipp: Wenn du so gefragt wirst, geht es wahrscheinlich doch, nur hast du es wohl falsch gemacht 😉



  • Das ist mir schon klar, aber ich dachte vielleicht erklärt es mir jemand 😃 Naja ich habe jetzt das Netz durchforstet und habe die Lösung gefunden. Danach stieß ich auf 3 weitere Fehler die ich behoben habe und nun komme ich wieder nicht weiter weil ich es echt nicht verstehe, vielleicht habt ihr einen Plan. Hier erstmal Test Nr.1 :

    else if(menueP == 2)
    			{
    				//Schattenwanderer wird erstellt
    				Schattenwanderer spieler;
    				spielerP = &spieler;
    				
    				cout<<"Name: "<<spielerP->getName()<<endl;
    				
    				choosed = true;
    			}
    

    Hier teste ich ob die Instanz vom Schattenwanderer an mein Champion-Objekt-Pointer spielerP übergeben wurde indem ich über spielerP die getName()-Funktion abrufe. Das funktioniert auch einwandfrei. So, 33 Zeilen weiter versuche ich die selbe Ausgabe:

    
    		}while(choosed == false);
    	}
    	//
    	//_________________
    	//CHAMPION AUSWAHL
    	//_________________
    	//
    	//
    	//_________________
    	//DAS MENUE
    	//_________________
    	//
    	
    	//Champion-Auswahl erzeugen
    	if(choosed == true)
    	{
    		do
    		{
    			cout<<"_______________________"<<endl;
    			cout<<"         MENUE  "<<endl;
    			cout<<"_______________________"<<endl;
    			cout<<"1 - Kampfzonen"<<endl;
    			cout<<"2 - Arena"<<endl;
    			cout<<"3 - Freier Kampf(Ohne EP)"<<endl;
    			cout<<"4 - Champion Infos"<<endl;
    			cout<<"5 - Beenden"<<endl;
    			
    			//-- Hier schmiert das Programm ab --//
    			cout<<"Name: "<<spielerP->getName()<<endl;
    			//-- 
    

    Wie ihr seht passiert dazwischen nicht großartig irgendetwas und trotzdem schmiert das Programm einfach ohne Fehlermeldung ab. Komischerweise ist das aber nur beim Schattenwanderer-Objekt so, der Schlaechter funktioniert, ist jedoch exakt gleich aufgebaut, nur mit anderem Namen:

    if(menueP == 1)
    			{
    				//Schlaechter wird erstellt
    				Schlaechter spieler;
    				spielerP = &spieler;
    				choosed = true;
    			
    			}
    

    Ja, mal sehen wann ich den Thread schließen kann haha, aber ich bin sehr dankbar das ihr versucht mir zu helfen (: schönen Abend noch an der Stelle.



  • Am Ende des if Blocks wird dein 'spieler' Objekt zerstört. Danach zeigt dein Zeiger irgendwo ins Nirvana und dein Programm kann nichts mehr damit anfangen.



  • Das wusste ich zwar aber mich wundert es dann das es troztdem mit dem Schlaechter-Objekt funktioniert hat aber das kannst du mir ja vielleicht noch erklären? Ich wäre dir sehr verbunden 😃

    Ich habe das Problem jetzt wie folgt gelöst indem ich die ganzen vorhandenen Champions erst deklariere:

    //VARIABLEN
    //
    		//Spieler Initialisieren
    		Champion *spielerP;
    		
    		//Champions initialisieren
    		Schattenwanderer schattenwanderer;
    		Schlaechter schlaechter;
    
    

    und sie dann im if-Block erst/nur die Zuweisung bekommen:

    if(menueP == 1)
    			{
    				//Schlaechter wird erstellt
    				spielerP = &schlaechter;
    				choosed = true;
    			
    			}
    			else if(menueP == 2)
    			{
    				//Schattenwanderer wird erstellt
    				spielerP = &schattenwanderer;
    				choosed = true;
    			}
    

    Ich danke vielmals für eure Hilfe und würde den Thread dann schließen (:



  • @levyeme sagte in [GELÖST] (Anfänger) ohne includierung Code implementieren?:

    choosed = true;

    Es heißt "chosen".

    Ich würd eher einen unique_ptr<> nehmen:

    #include <iostream>
    #include <memory>
    #include <limits>
    
    class Base {
    public:
    	virtual ~Base() {}
    	virtual void bark() = 0;
    };
    
    class A : public Base {
    public:
    	 void bark() override { std::cout << "Wau!\n"; }
    };
    
    class B : public Base {
    public:
    	void bark() override { std::cout << "Wuff!\n"; }
    };
    
    std::unique_ptr<Base> create_dog(int type)
    {
    	switch (type) {
    	case 1:
    		return std::make_unique<A>();
    	case 2:
    		return std::make_unique<B>();
    	}
    	return nullptr;
    }
    
    int main()
    {
    	int choice{};
    	while (choice != 1 && choice != 2) {
    		if (!(std::cin >> choice)) {
    			std::cin.clear();
    			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    		}
    	}
    	
    	std::unique_ptr<Base> dog{ create_dog(choice) };
    	dog->bark();
    }
    

    dann liegt keine Schattenwanderer- bzw Schlaechterleiche rum, die nicht benötigt wird.



  • @levyeme Wenn das Objekt zerstört wird, heißt es nicht, dass im Speicher nur noch nullen oder so stehen, sondern da steht halt irgendwas. Daher kann sein, dass das zufällig funktioniert. Aber, dass ist halt Zufall.



  • @swordfish sagte in [GELÖST] (Anfänger) ohne includierung Code implementieren?:

    @levyeme sagte in [GELÖST] (Anfänger) ohne includierung Code implementieren?:

    choosed = true;

    Es heißt "choosen".

    Nö, "chosen" 😉



  • omg, ich geh heulen 😢 ... naja, zumindest war ich näher dran 😉



  • @Swordfish Will hier nicht rum klug scheißen, aber warum verpackst du dein switch Konstrukt nicht in eine saubere Factory Funktion? Du schmeißt hier einem offensichtlichen Anfänger gleich 2 "Fehler" vor die Füße. Dein std::unique_ptr<Base> dog; erstellst du viel zu früh. Würdest du das vll noch umändern, damit man direkt ein "richtiges" Beispiel hat?



  • passts jetzt? ^^


Log in to reply