Мой друг и я изучаем C ++, и хотя мы смогли побороть все проблемы, которые возникли у нас (и многому научились, благодаря этой программе), эта программа заставляет нас ломать голову весь день. Мы потратили бесчисленное количество часов, не только пытаясь решить их самостоятельно, но и просматривая связанные вопросы Stackoverflow и проводя тонны поисков в Google … Наконец, мы решили, что нам нужно просто спросить и надеяться, что один из вас поймет, в чем заключается наша проблема. ,
По сути, мы пытаемся создать текстовую (только консольную) RPG, и мы дошли до того, что мы создаем статистику игрока, используя класс, определенный в нашем единственном заголовочном файле, есть три конструктора для класса (с использованием перегрузки функций). конечно) и хотя мы можем запустить игру без ошибок, кажется, что мы не можем на самом деле редактировать значения переменных членов класса!
Это наш класс:
//File OverHeader.h
class PlayerStatistics
{
public:
PlayerStatistics(int HitPoints, int MagickaPoints, int Fatigue, int Damage, int Defense, int Dodge, int Block, int SpellCastChance);
PlayerStatistics(int Experience, int Level);
PlayerStatistics();
int HitPoints;
int MagickaPoints;
int Fatigue;
int Damage;
int Defense;
// Chance Based System (Relies on Fatigue Level)
int Dodge;
int Block;
int SpellCastChance;
int Experience;
int Level;
};
И основная функция:
#include <iostream>
#include <string>
#include "OverHeader.h"
// MAIN FUNCTION DEFINITION
int main()
{
PlayerStatistics PlayerStats(20, 20, 20, 20, 20, 20, 20, 20);
PlayerStatistics PlayerStatsLevel(0, 1);
//continued with code irrelevant to this question.
}
Проблема в том, что строки в главной функции на самом деле не устанавливают целочисленные переменные в классе на эти значения. После этих двух строк целочисленные значения должны быть установлены (только для демонстрационных целей):
int HitPoints == 20;
int MagickaPoints == 20;
int Fatigue == 20;
int Damage == 20;
int Defense == 20;
int Dodge == 20;
int Block == 20;
int SpellCostChance == 20;
int Experience == 0;
int Level == 1;
Но как ни странно, вывод ЛЮБОГО из этих целых чисел будет просто выводить случайные числа (предположительно, память обращается к текущим значениям).
Три конструктора на самом деле определены правильно (хотя не в Main.cpp) здесь:
// PlayerCreation.cpp
PlayerStatistics::PlayerStatistics(int HitPoints, int MagickaPoints, int Fatigue, int Damage, int Defense, int Dodge, int Block, int SpellCastChance)
{
}
PlayerStatistics::PlayerStatistics(int Experience, int Level)
{
}
PlayerStatistics::PlayerStatistics()
{
}
И это наша проблема, я надеюсь, что я все описал достаточно четко, пожалуйста, дайте мне знать, если вы можете помочь нам на самом деле редактировать значения этих переменных членов класса! Вся помощь приветствуется!
Это создает один и тот же класс двумя разными способами:
PlayerStatistics PlayerStats(20, 20, 20, 20, 20, 20, 20, 20);
PlayerStatistics PlayerStatsLevel(0, 1);
Первый создает переменную с именем PlayerStats
который использует первый конструктор. Вторая создает другую переменную с именем PlayerStatsLevel
который использует второй конструктор.
Теперь конструкторы …
// PlayerCreation.cpp
PlayerStatistics::PlayerStatistics(int HitPoints, int MagickaPoints, int Fatigue, int Damage, int Defense, int Dodge, int Block, int SpellCastChance)
{
}
PlayerStatistics::PlayerStatistics(int Experience, int Level)
{
}
Это на самом деле не инициализирует переменные-члены в классе. Вы использовали те же имена в конструкторе, но на самом деле это принесет вам горе, потому что (для одного примера) локальная переменная HitPoints
передается в конструктор переопределяет член класса HitPoints
, Теперь, если вы хотите обратиться к члену класса, вы должны использовать this->HitPoints
,
Итак, повторюсь, ничего на самом деле не было инициализировано. Таким образом, у вас есть случайные значения в вашем объекте. Вы должны сделать это (я возьму более короткий пример):
// Using initializer list
PlayerStatistics::PlayerStatistics(int inExperience, int inLevel)
: Experience(inExperience), Level(inLevel)
{
}
// Or using conventional assignment
PlayerStatistics::PlayerStatistics(int inExperience, int inLevel)
{
Experience = inExperience;
Level = inLevel;
}
Обратите внимание, что другие значения не были инициализированы с помощью этого конструктора. Это может быть предназначено, или вы можете установить для них всех значение по умолчанию. Вы должны сделать это явно.
Теперь, похоже, вы хотели один экземпляр со всей этой установленной статистикой. Что вы можете сделать, это использовать только один конструктор — пустой конструктор PlayerStatistics()
и инициализировать все к чему-то «разумному». Затем определите функции для установки статистики в чанках:
void PlayerStatistics::SetStats(int HitPoints, int MagickaPoints, int Fatigue, int Damage, int Defense, int Dodge, int Block, int SpellCastChance)
{
this->HitPoints = HitPoints;
this->MagickaPoints = MagickaPoints;
// etc etc...
}
void PlayerStatistics::SetLevel(int Experience, int Level)
{
this->Experience = Experience;
this->Level = Level;
}
// If you want you can explicitly set the values to something in the constructor.
// It's probably good practice if you're new at this.
PlayerStatistics::PlayerStatistics()
{
SetStats(0, 0, 0, 0, 0, 0, 0, 0);
SetLevel(0, 0);
}
Теперь в вашем основном:
PlayerStatistics player;
player.SetStats(20, 20, 20, 20, 20, 20, 20, 20);
player.SetLevel(0, 1);
Или, если это настройки по умолчанию для нового игрока, сделайте это в конструкторе, и тогда вам никогда не придется помнить.
Надеюсь, что вы начали. Веселись и никогда не бойся экспериментировать.
Эти конструкторы не определены правильно: они принимают аргументы, но ничего не делают со значениями! Попробуйте это вместо этого:
PlayerStatistics::PlayerStatistics(int Experience, int Level)
:
Experience(Experience),
Level(Level)
{
}
Это примерно эквивалентно:
PlayerStatistics::PlayerStatistics(int Experience, int Level)
{
this->Experience = Experience;
this->Level = Level
}
Конечно, вы хотите инициализировать другие таким же образом и установить для неопределенных полей их значения по умолчанию, но вы поняли идею.
Ваш конструктор не устанавливает значения — конструкторы могут иметь любые параметры, которые вам нравятся, и эти параметры не присваиваются элементам данных только потому, что они имеют одинаковые имена.
Тебе нужно:
PlayerStatistics::PlayerStatistics(
int HitPoints, int MagickaPoints, int Fatigue,
int Damage, int Defense, int Dodge, int Block,
int SpellCastChance) :
HitPoints(HitPoints),
MagickaPoints(MagickaPoints),
... etc ...
{
}
(сделайте отступ, как вам нравится, я сделал это таким образом, потому что, кажется, нет особой разницы, единственная разница между моим кодом и вашим невидимым при прокрутке вправо).
: HitPoints(HitPoints) ...
является «списком инициализации», и это означает «инициализировать этот базовый класс или элемент данных этим значением». В вашем случае значение имеет то же имя, что и элемент данных, но это нормально, компилятор выясняет, какой из контекста.