C++ Variablen "verknüpfen" aus zwei Klassen.



  • Wenn du die Getter-Funktionen korrekt mit return implementiert hast, dann kannst du, wie vorher auf die Membervariable zugreifen:

    cout << Player1.getPlayerName();
    

    oder

    std::string name = Player1.getPlayerName();
    

    (die einzelne Anweisung Player1.getPlayerName(); führt zwar die Funktion aus, macht aber dann nichts mit dem Ergebnis - der Compiler sollte aber eine Warnung dafür ausgeben, denn mit Optimierungen würde der Compiler den ganzen Aufrufcode dafür eliminieren).



  • @100Lifes sagte in C++ Variablen "verknüpfen" aus zwei Klassen.:

    Kleine Frage: Ich habe versucht void Player::getPlayerName() zu string Player::getPlayerName() umzustellen (in der c_Player.cpp und c_Player.hpp) um den Output in einer Variable zu speichern. Ohne Erfolg obwohl ich dann cout << this->PlayerName zu return this->PlayerName gemacht habe. Was hab ich da verpennt?

    Das klingt generell erstmal richtig - das solltest du auch machen! Daher: keine Ahnung, was du da verpennt hast 🙂

    Ich habe noch den Konstruktor von Player und Weapon etwas umgebaut:

    Warum die Konstruktoren ohne Parameter? Soll es wirklich Spieler ohne festgelegte Namen geben oder Waffen, bei denen noch nichts festgelegt ist? Wenn du ein Weapon weapon; erzeugst, ist darin erstmal gar nichts festgelegt. Eventuell wäre es sinnvoll, einer solchen Waffe 0 min/max/crit Schaden zu geben - oder aber den Construktor ganz zu streichen.



  • Hab es nochmals probiert mit dem return... vielleicht hab ich vorher in den .hpp dateien verpennt std::string zu machen und hab nur string eingegeben zur funktions return value.

    @wob Ich habe den leeren Constructor weil sich gerade bei der Waffe herausgestellt hat, dass wenn ich ein Player eruzeuge und ohne leeren Constructor ran gehe ich mehr Fehlermeldungen erhalte als es Reis in China gibt gefühlt.
    Das ich eine "None" Waffe einfüge oder sowas wäre evtl. eine Idee um Bugs zu verhindern was durchaus ein valider Punkt ist.

    Aber ich bin gerade echt froh, dass ich heute endlich mal ein bisschen Fortschritt machen konnte.



  • Tja, aller Anfang ist schwer, aber ich habe den Eindruck, du bist auf einem guten Wege. Viel Erfolg weiterhin.



  • Vielen Dank für all die Hilfe @Th69 , @wob und allen anderen. ^^

    Eine kleine letzte Frage noch.
    Jetzt hab ich ja ein Userinput den ich zuerst in eine lokale variable abfange und dann der Funktion übergebe. Kann ich das eigentlich irgendwie auch in einer Zeile machen weil es lässig wäre?

    	cin >> UserInput;
    	Player1.setPlayerName(UserInput);
    


  • @100Lifes sagte in C++ Variablen "verknüpfen" aus zwei Klassen.:

    Vielen Dank für all die Hilfe @Th69 , @wob und allen anderen. ^^

    Eine kleine letzte Frage noch.
    Jetzt hab ich ja ein Userinput den ich zuerst in eine lokale variable abfange und dann der Funktion übergebe. Kann ich das eigentlich irgendwie auch in einer Zeile machen weil es lässig wäre?

    	cin >> UserInput;
    	Player1.setPlayerName(UserInput);
    

    Erstmal nein.

    Wichtigster Grund: das "setPlayerName()" soll nicht wissen müssen, woher der Namen kommt. Ob von der Tastatur eingelesen, aus einem Savegame eingelesen, aus einem Onlinedienst für zufällige Namen etc.

    Was du natürlich aber machen kann (die Antwort lautet also "Ja"): schreibe dir eine Funktion, die dir einen Usernamen einliest.

    Also im einfachsten Falle:

    std::string askForPlayername() {
        std::cout << "Bitte gib einen Spielernamen ein!\n";
        std::string username;
        std::cin >> username;  // vielleicht willst du auch mit getline arbeiten, um Leerzeichen im Namen zu erlauben
        return username;
    }
    
    [...]
    
    player1.setPlayerName(askForPlayername());


  • getline wäre noch ein guter input aber in dem Fall lohnt es sich wohl eher nicht dafür eine Funktion zu schreiben. Dann lassen wir das so und danke nochmals ^^



  • @100Lifes sagte in C++ Variablen "verknüpfen" aus zwei Klassen.:

    getline wäre noch ein guter input aber in dem Fall lohnt es sich wohl eher nicht dafür eine Funktion zu schreiben. Dann lassen wir das so und danke nochmals ^^

    Doch, das lohnt sich (fast) immer. Kleine Funktionen sind super!



  • @wob Ja gut, dann hab ich jetzt eine Funktion gemacht die evtl sogar etwas flexibler ist als zunächst angenommen....
    Nur kommt jetzt eine Frage und ich hab das Gefühl es ist was total logisches.

    Functions.cpp

    #include "FunctionCollector.hpp"
    void RequestPlayerName(bool InputType) {
    	// InputType = True -> UserInput
    	//			 = False -> SaveFile
    	if (InputType == true) {
    		string NewUserName;
    		cout << "Setze deinen Spierlnamen: ";
    		cin >> NewUserName;
    		Player1.setPlayerName(NewUserName);
    	} else {
    		cout << "Read from SaveFile not supported yet";
    	}
    }
    

    FunctionCollector.hpp

    #include <iostream>
    
    #include "c_Weapon.hpp"
    #include "c_Player.hpp"
    void RequestPlayerName(bool);
    

    MainGame.cpp

    #include "c_Weapon.hpp"
    #include "c_Player.hpp"
    #include "FunctionCollector.hpp"
    
    	RequestPlayerName(true);
    	cout << "Der Spielername ist: " << Player1.getPlayerName();
    

    Ich erhalte aus Functions.cpp die Meldung, dass Player1 ein "nichtdeklarierter Bezeichner" ist.
    Da ich aber in Functions.cpp die FunctionCollector.hpp Datei inkludiert habe und dort drin dann c_Player.hpp müsste das doch eigentlich funktionieren nicht?



  • RequestPlayerName ist eine freie Funktion und kennt den Spieler daher nicht:

    void RequestPlayerName(Player& Player1, bool InputType) {
    	// InputType = True -> UserInput
    	//	     = False -> SaveFile
    	if (InputType == true) {
            ...
            }
    }
    

    Die Signatur der (ohnehin falschen) Deklaration in der hpp müsste angepasst werden. InputType ist als Bezeichner allerdings auch ein wenig irreführend.
    Beachte auch if (InputType == true), if (InputType = true) ist eine Zuweisung (und die Bedingung ist immer erfüllt). Daher wird auch eigentlich immer das kürzere if (InputType) verwendet. Die umgekehrte Bedingung könnte man dann auch statt if (InputType == false) als if (!InputType) schreiben.
    Das ist ein wenig Gewöhnungssache, aber kürzerer Code ist in vielen Fällen auch schneller zu erfassen.



  • Das mit dem == stimmt und hab ich nachträglich noch kurz korrigiert gehabt.
    Aber das if (InputType) <-- wenn bool, funktioniert wusst ich nicht.

    Auf jeden Fall hab ich die Funktion wie von dir vorgeschlagen noch um den Verweis erweitert nur erhalte ich jetzt folgende Fehlermeldung:

    1>MainGame.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl RequestPlayerName(bool)" (?RequestPlayerName@@YAX_N@Z)" in Funktion "main".
    1>  Hinweis zu Symbolen, die definiert wurden und möglicherweise übereinstimmen:
    1>    "void __cdecl RequestPlayerName(class Player &,bool)" (?RequestPlayerName@@YAXAEAVPlayer@@_N@Z)
    


  • Ok, habs selbst geklärt. Musste das Beispiel von @wog nochmals etwas im Detail anschauen.

    Habe jetzt FunctionCollector.hpp um string RequestPlayerName(bool); erweitert und in Functions.cpp folgendes reingeschrieben:

    string RequestPlayerName(bool InputType) {
    	// InputType = True -> UserInput
    	//			 = False -> SaveFile
    	string NewUserName;
    	if (InputType) {
    		cout << "Setze deinen Spierlnamen: ";
    		cin >> NewUserName;
    	}
    	else {
    		cout << "Read from SaveFile not supported yet";
    	}
    
    	return NewUserName;
    }
    

    So konnte ich dann in der int main() Funktion dann folgendermassen darauf zugreiffen:

    	Player1.setPlayerName(RequestPlayerName(true));
    	cout << "Der Spielername ist: " << Player1.getPlayerName();