Abgeleitete Klasse gibt als "Name" fälschlicherweise nicht aus



  • Hey liebe Community,

    ich habe ein Problem mit meinem Code.

    In der Hauptklasse "weapon" steht die Funktion getWeaponName(). Diese müsste ja bei Geerbten Klassen mitgeerbt werden oder nicht.

    Wenn ich jetzt aber den Namen von einem geerbten Objekt haben will, gibt er dafür einfach "" aus (Also nicht). Ich bekomme keine Fehler.

    Muss ich wirklich in den Geerbten Klassen, die Funktion "überschreiben" (oder zählt das dann schon als überladen)?

    Weiß jemand weiter?

    Der Code: (Erklärung warum er so "Blöd" geschrieben ist, ist unter dem Code)

    player.h (Die Waffen werde ich später in eine eigene Header/CPP umschieben)

    #pragma once
    #include <iostream>
    #include <string>
    using namespace std;
    
    //Vorwärtsdekl.
    class weapon;
    class skills;
    
    //Class Player mit allen Werten und Funkt.
    class player {
    private:
    	string _name;
    	weapon *_playerWeapon; //Erstellt ein Objekt von einer Vererbten Klasse von "weapon"
    	skills **__skills; //Speichert ein Array von "skills-Pointer", in denen man von "skills"-vererbte Objekte speichern kann
    	int _level;
    	int _life;
    	int _mana;
    	bool _critchance_bool;
    	int _critchance;
    	int _skillcount;
    public:
    	player(int, int, int, bool, int, int, string); //Konstr.
    	void levelUP(); //Funkt. zum Upleveln (Nur für Tests.. Noch kein Lvl-System impl.)
    	int hit(int damage); //Einkommender Angriff. Leben wird - damage
    	bool dead(); //Wenn Leben <= 0, wird das Spiel beendet (Deathmessage)
    	void setLife(int life); //Zum Healen des Spielers z.B. mit Pots.
    	void setMana(int mana); //Das gleiche wie setLife
    	int getLevel(); //Da Lvl private ist, getter-Meth
    	int getLife(); //Schau getLevel
    	int getMana(); //Schau getLevel
    	int getWeaponDmg(); //nutzt _playerWeapon->getDmg(); um den Dmg der Waffe bzw. eines Normalen Angriffes zu bekommen
    	string getWeaponName(); //nutzt _playerWeapon->getName(); um den Namen ""
    };
    
    //Parentclass weapon zum Erstellen der versch. Waffen
    class weapon {
    private:
    	int _dmg;
    	string _name;
    public:
    	int getWeaponDmg();
    	string getWeaponName();
    };
    
    //Waffe: Bauernschwert
    class weapon_bauernschwert : public weapon {
    private:
    	int _dmg = 3;
    	string _name = "Bauernschwert";
    };
    
    //Waffe: Scharfe Schauel
    class weapon_scharfe_schaufel : public weapon {
    private:
    	int _dmg = 10;
    	string _name = "Scharfe Schaufel";
    };
    
    //Waffe: Kriegerisches Langschwert
    class weapon_kriegerisches_langschwert : public weapon {
    	int dmg = 30;
    	string _name = "Kriegerisches Langschwert";
    };
    

    Und nun die .cpp (Zeile 44 ist der Aufruf):

    #include <iostream>
    #include <string>
    #include "player.h"
    using namespace std;
    
    //Gibt Waffenname (Wird von anderen weapon_xxx-Klassen geerbt)
    string weapon::getWeaponName() {
    	return _name;
    }
    
    //Gibt Waffenschaden (Wird von anderen weapon_xxx-Klassen geerbt)
    int weapon::getWeaponDmg() {
    	return _dmg;
    }
    
    //Constructor der player-Klasse
    player::player(int level, int life, int mana, bool critchance_bool, int critchance, int skillcount, string name) {
    	_level = level;
    	_life = life;
    	_mana = mana;
    	_critchance_bool = critchance_bool;
    	_critchance = critchance;
    	skills **__skills = new skills*[4]; //Erstellt ein skills*-Array mit 4 Elementen (Der Spieler soll bis zu 4 Skills nutzen können)
    	_skillcount = skillcount;
    	_playerWeapon = new weapon_bauernschwert();  //Erstellt ein Objekt von weapon_bauernschert und der *_playWeapon zeigt nun darauf
    	_name = name;
    
    	//Gibt alle Stats aus
    	cout << "Du hast soeben einen Charakter erstellt!" << endl << "Name:\t\t" << _name << endl << "Level:\t\t" << _level <<
    		endl << "Leben:\t\t" << _life << endl << "Mana:\t\t" << _mana << endl << "Critchance:\t" << _critchance << endl <<
    		"Skills:";
    
    	if (_skillcount == 0) {
    		cout << "\t\tDu besitzt keine Skills!" << endl;
    	}
    	else { //Da Skillklasse noch nicht beschrieben, ist hier alles Kommentiert
    		/*
    		cout << endl;
    		for(int i = _skillcount; i < 4; i++){
    			cout << _skill[i]->getSkillName() << "  : Damage: " << _skill[i]->getSkillDmg() << endl;
    		}*/
    	}
    
    	//Gibt Waffenname aus !!!!BUG!!!! ---Waffenname wird nicht angezeigt!!!!!---
    	cout << "Waffe:\t\t" << _playerWeapon->getWeaponName() << endl;
    }
    

    Zur Erklärung warum der Code so aussieht, wie er aussieht:
    Ich Programmiere gerade ein kleines Minispiel, um mit C++ für die Hochschule ein noch ein wenig klar zu kommen (kann bereits Bäume, verk. Listen, iteratoren etc. Ist ja auch uninteressant). Schreibe bald die Klausur und will alles nochmal vertiefen und wirklich mal eigenständig was programmieren.

    Aufjedenfall will ich in dem Spiel 2 Entwurfsmuster nutzen (Decorator evtl für ein Pet mit Rüstung, die Pro Teil, ihn weiter Dekoriert oder sowas.. Und Strategie für die Mobs und deren Attacken).
    Deswegen macht es für euch wahrscheinlich keinen Sinn, dass die Waffe ein Objekt ist oder die Skills ein skill*-Array mit Skillobjekten (Man könnte ja alles in einer Datenbank speichern. 😃 )

    Vielleicht noch eine weitere Frage: Wie bewertet ihr mein Programmiermuster bzw. wie ich den Code strukturiere etc.? Ist halt das erste Projekt, das ich mir selber überlegt habe (Nichts von einer Aufgabe von der Hochschule).



  • Du definierst in jeder abgeleiteten Klasse eine eigene Variable _name. Die Funktion gibt den der Basis aus.



  • Danke für die schnelle Antwort!

    Heißt, Funktionen überschreiben?

    Jetzt bekomme ich einen Linking-Fehler

    Fehler LNK2001 Nicht aufgelöstes externes Symbol ""public: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall weapon::getWeaponName(void)" (?getWeaponName@weapon@@UAE?AV?basic_string@DU?basic\_string@DU?char_traits@D@std@@V?$allocator@D@2@@std@@XZ)". Charaktererstellen C:\Users\***\source\repos\Charaktererstellen\Charaktererstellen\player.obj 1

    Fehler LNK2001 Nicht aufgelöstes externes Symbol ""public: virtual int __thiscall weapon::getWeaponDmg(void)" (?getWeaponDmg@weapon@@UAEHXZ)". Charaktererstellen C:\Users\***\source\repos\Charaktererstellen\Charaktererstellen\player.obj 1

    Fehler LNK1120 2 nicht aufgelöste Externe Charaktererstellen C:\Users\***\source\repos\Charaktererstellen\Debug\Charaktererstellen.exe 1



  • Megani schrieb:

    Heißt, Funktionen überschreiben?

    Hast du Bedarf an mehreren Namensvariablen?
    Möchtest du den Code der Funktion in jeder Klasse als Kopie einfügen?



  • Ja. Die Funktion soll halt die Namen der geerbten Klasse ausgeben. Ich dachte, wenn man eine Klasse erbt, erbt man die Funktionen so mit, wie sie sind.

    Heißt, dass die auch den Namen, der geerbten Klasse ausgeben.

    Habe jetzt mal getestet, den Geerbten Klassen die Funtkionen zu überschreiben, bekomme aber einen Linking-Fehler(Der verherige Kommentar von mir wurde mit den Zitaten der Fehler "erweitert".

    Edit: Jetzt geht es, aber halt mir dem überschreiben.

    Den Fehler habe ich wegbekommen, indem ich die Funktionen Hauptklasse(oder heißt es Parentclass?) "weapon" als virtual .... = 0; gesetzt habe. Hatte das "= 0;" vergessen.



  • Du musst in deinen abgeleiteten Klassen _name initialisieren und nicht neu definieren. Wenn du _name aus der Basisklasse initialisierst wird dir auch der name mit deiner Funktion ausgegeben.

    Am besten deklarierst du _name innerhalb deiner Basisklasse als protected .

    PS: Der Linkerfehler kommt daher das du eine Funktionsdefinition gemacht hast ohne dieser einen Funktionsrumpf zu geben.



  • string Name und int Dmg sind ja in der Hauptklasse drin, aber wenn ich dann Name = "" in der abg. Klasse schreibe, zeigt er mir nen Fehler an, dass ich doch bitte eine Variablenart davorschreiben möchte.
    😕



  • Megani schrieb:

    Ja. Die Funktion soll halt die Namen der geerbten Klasse ausgeben.

    Dann solltest du den Namen auch setzen und nicht einen weiteren erfinden.

    Ich dachte, wenn man eine Klasse erbt, erbt man die Funktionen so mit, wie sie sind.

    Wo ist der Widerspruch?



  • Ich glaube, ich bin einfach noch nicht so gut in C++... Das mit Protected hat mich gerade daran erinnert, dass ja Variablen, die in der Hauptklasse private sind, nicht von geerbten Klassen mitgeerbt werden..

    Wie kann ich diese jetzt aber in den geerbt. Klassen auf private setzten?

    Muss ich einfach

    class weapon_xx : private weapon
    

    schreiben?



  • Megani schrieb:

    string Name und int Dmg sind ja in der Hauptklasse drin, aber wenn ich dann Name = "" in der abg. Klasse schreibe, zeigt er mir nen Fehler an, dass ich doch bitte eine Variablenart davorschreiben möchte.
    😕

    Ist das der einzige Weg, einer Variablen bei der Objektkonstruktion einen Wert zu geben?



  • Sonst fällt mir nurnoch der Konstruktor ein.



  • Megani schrieb:

    Das mit Protected hat mich gerade daran erinnert, dass ja Variablen, die in der Hauptklasse private sind, nicht von geerbten Klassen mitgeerbt werden..

    Das ist falsch.



  • Megani schrieb:

    Sonst fällt mir nurnoch der Konstruktor ein.

    Warum nur noch? Was ist falsch an einem Konstruktor?



  • Ich mag den nicht wirklich.

    Weil ich da noch nicht genau weiß, wie ich den Konstruktor schreiben soll.

    Ob ich den miterbe oder ob ich den neuschreibe. Wie ich den schreibe und wie ich vorallem den Dekonstr. schreibe.

    ich weiß auch nicht, wie man ein Obj., dass man mit new erstellt hat, wieder löschen kann und den Pointer weiter nutzen kann um z.B. eine andere geerbte Klasse darin zu speichern. Mit delete und delete[] bekomme ich immer Fehler.



  • Dann solltest du nicht mit Entwurfsmustern spielen sondern die Grundlagen lernen.



  • manni66 schrieb:

    Dann solltest du nicht mit Entwurfsmustern spielen sondern die Grundlagen lernen.

    Was ich gerade mit diesem Projekt tuhe.

    Edit: Es geht jetzt.


Anmelden zum Antworten