2016-08-20 7 views
0

Ich bin ziemlich neu in C++, aber das hat mich ratlos. Ich arbeite an dem Basiscode für ein RPG, aber dieser eine Charakter in der Klasse hat mich ratlos gemacht. Ich habe die fraglichen Stücke hier isoliert (es gibt gut 1000 ausgeschnittene Linien), und das Problem bleibt bestehen.Klassenobjekt (char) ändert sich nach Funktion

Hier ist die Klasse und Header für das Programm:

#include <iostream> 
#include <cstdlib> 
using namespace std; 

unsigned long errorcount; 
// I know this is bad coding, but it's not going to be in the end product... 

class character { 
public: 
    void setgender(char newgender); 
    char getgender() const; 
private: 
    char gender; 
}; 

void character::setgender(char newgender) { 
    switch (newgender) { 
    case 'M': gender = 'M'; break; 
    case 'F': gender = 'F'; break; 
    default: gender = '0'; errorcount++; break; 
    } 
    std::cout << "\nDuring setgender function: " << gender; 
    return; 
} 

char character::getgender() const { 
    std::cout << "\nDuring getgender function: " << gender; 
    return gender; 
} 

Dieser nächste Teil, den ich meinen Kopf hat kratzen. Ich begann den folgenden Code:

void PlayerCharacterCreation(character Player) { 
    string newgender; 
    while(true) { 
    std::cout << "\nAre you male or female?" << "\n1. Male" << "\n2. Female" << "\n::"; 
    std::cin >> newgender; 
    if (newgender == "1") { Player.setgender('M'); break; } 
    if (newgender == "2") { Player.setgender('F'); break; } 
    std::cout << "\nInvalid response. Try again."; 
    } 
    std::cout << "\nAfter setgender function: " << Player.getgender(); 
} 

void PlayerCreationTest() { 
    character Test; 
    PlayerCharacterCreation(Test); 
    char playergender = Test.getgender(); 
    if (playergender != 'M' && playergender != 'F') { errorcount++; } 
    std::cout << "\nAfter getgender function: " << playergender; 
    std::cout << "\n\nOUTPUT BEGINS NOW\nGender: " << playergender << "\n"; 
    std::cout << "OUTPUT ENDS. Total Errors: " << errorcount << "."; 
    return; 
} 

int main() { 
    PlayerCreationTest(); 
    return 0; 
} 

Nun, soweit ich das beurteilen kann, es ist nichts falsch mit irgendetwas davon - der (GCC) Compiler beschwert sich nicht, und es funktioniert gut bis zu einem gewissen Punkt. Aber wenn ich es laufen lasse, erhalte ich die folgende Ausgabe:

Are you male or female? 
1. Male 
2. Female 
1 
During setgender function: M 
During getgender function: M 
After setgender function: M 
During getgender function: @ 
After getgender function: @ 
OUTPUT BEGINS NOW  
Gender: @ 
OUTPUT ENDS. Total Errors: 1. 

Schlimmer noch, wenn ich Option „2“ der Ausgang das gleiche nur, wenn es keinen Sinn macht:

Are you male or female? 
1. Male 
2. Female 
2 
During setgender function: F 
During getgender function: F 
After setgender function: F 
During getgender function: @ 
After getgender function: @ 
OUTPUT BEGINS NOW 
Gender: @ 
OUTPUT ENDS. Total Errors: 1. 

In Mit anderen Worten, die erwartete Ausgabe verläuft irgendwo zwischen der letzten Zeile von PlayerCharacterCreation() und der nächsten Zeile der PlayerCreationTest() schlecht falsch.

Soweit ich sagen kann, sollte die "Charakter" -Klasse zwischen den Funktionen bleiben, nicht alle willy-nilly so ändern.

Ich hoffe, das ist genug für jemanden, um herauszufinden, was ich falsch mache, aber ich spielte mit ihm ein wenig und schaffte es, den Ausgangscharakter noch mehr zu ändern.

Durch Hinzufügen eines „srand (0)“ Zeile am Beginn der Hauptfunktion, I kann die Änderung ‚@‘ in einem ‚Y‘ für beiden Optionen 1 und 2

Durch das Hinzufügen einer „GenderTest() "Zeile am Anfang der Hauptfunktion, ich kann das '@' zu einem 'F' ändern, für beide Optionen. Wenn ich beide Zeilen hinzufüge, scheint nur die unmittelbar über der "PlayerCreationTest()" - Zeile zu liegen. Das ist seltsam, weil der vollständige Code immer ein 'l' (Kleinbuchstaben L) anstelle von '@' zurückgibt, und die Hauptfunktion ist genau die gleiche wie oben beschrieben.

+0

auf die Begriffe "nach Wert" Lesen und "by reference". Das Argument 'PlayerCharacterCreation()' wird als Wert übergeben, während das erwartete Verhalten darin besteht, dass das Argument als Verweis übergeben wird. – Peter

Antwort

2

Soweit ich sagen kann, sollte die "Charakter" -Klasse zwischen den Funktionen gleich bleiben, nicht alle Willy-Nilly so ändern.

Nun, Sie irren sich. Sie bleiben gleich, denn sie sind separate Variablen. PlayerCharacterCreation erstellt eine lokale character (eine Kopie von Test), und am Ende der Funktion wird das Objekt zerstört.

Das Original character, das Sie an PlayerCharacterCreation weitergegeben haben, hat sich nie geändert, und Sie erhalten einige seltsame Ausgabe, weil das Geschlecht nie für das character festgelegt wurde.

Die Player in PlayerCharacterCreation ist ein völlig neues character, es ist nicht Test :)

Wenn Sie die character weitergegeben PlayerCharacterCreation ändern möchten, müssen Sie es passieren durch Verweis (es gibt einige andere Möglichkeiten, auch wie ein Zeiger vorbei, Rückkehr Player, aber das ist die beste):

void PlayerCharacterCreation(character& Player); 
            ^^^ 
            reference 
+0

Danke! Das war alles was ich brauchte. Ich habe definitiv noch einen Weg zu gehen. –

1
void PlayerCharacterCreation(character Player) 

Innerhalb dieser Funktion ist eine lokale Instanz von character, in die der aufrufende Parameter kopiert wird. Beachten Sie Folgendes:

#include <iostream> 

void f1(int x) { 
    x++; 
} 

void f2(int i) { 
    i++; 
} 

int main() { 
    int i = 0; 
    f(i); 
    std::cout << i << '\n'; 
} 

Wir wissen, dass der Ausgang von diesem wird ‚0‘ sein, weil f1::x und f2::i ihre eigenen, unabhängigen Variablen aus unserem Quellparameter kopiert werden.

Wenn Sie eine bestimmte Instanz einer Variablen und nicht eine Kopie davon übergeben möchten, müssen Sie einen Zeiger oder eine Referenz angeben.

void by_pointer(Character* player) { 
    if (player == nullptr) { 
     error_handling(); 
    } 
    player->do_thing(); 
} 
by_pointer(&player); 

void by_reference(Character& player) { 
    player.do_thing(); 
} 
by_reference(player); 

Beispiel:

#include <iostream> 

int f1(int& param) { 
    param++; 
} 

int main() { 
    int i = 0; 
    f1(i); 
    std::cout << i << '\n'; // outputs 1 
} 
+0

Vielen Dank! Ich wusste, dass es etwas Einfaches sein musste. Funktioniert perfekt! –

Verwandte Themen