0

私の友人と私はC++を学んでおり、このプログラムで私たちが直面しているすべての問題を打ち負かすことができました(そしてそうすることでたくさんのことを学びました)が、これは私たちを一日中頭を悩ませています。私たちは自分たちで解決しようとするだけでなく、Stackoverflowの関連する質問を調べたり、大量のGoogle検索を実行したりするのに数え切れないほどの時間を費やしてきました... 。

基本的に、テキストベース(コンソールのみ)のRPGを作成しようとしていますが、唯一のヘッダーファイルで定義されたクラスを使用してプレーヤー統計を作成するところまで到達しました。クラスには3つのコンストラクターがあります(関数のオーバーロードを使用)もちろん)そしてゲームエラーなしで実行することはできますが、クラスメンバー変数の値を実際に編集することはできないようです!

これは私たちのクラスです:

//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.
}

問題は、Main関数の行が、クラス内の整数変数を実際にそれらの値に設定しないことです。これらの2行の後で、整数値を次のように設定する必要があります(デモンストレーションの目的で)。

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;

しかし、奇妙なことに、これらの整数のいずれかを出力すると、単に乱数が出力されます(おそらくメモリは現在の値をアドレス指定します)。

3つのコンストラクターは、実際にはここで適切に定義されています(ただし、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()
{

}

それが私たちの問題です。すべてを十分に明確に説明したことを願っています。これらのクラスメンバー変数の値を実際に編集するのに役立つかどうか教えてください。すべての助けに感謝します!

4

3 に答える 3

4

これにより、2つの異なる方法で同じクラスが作成されます。

PlayerStatistics PlayerStats(20, 20, 20, 20, 20, 20, 20, 20);
PlayerStatistics PlayerStatsLevel(0, 1);

PlayerStats1つ目は、最初のコンストラクターを使用するという変数を作成します。PlayerStatsLevel2番目は、2番目のコンストラクターを使用するという別の変数を作成します。

さて、コンストラクターは...

// 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コンストラクターで同じ名前を使用しましたが、(1つの例を挙げると)コンストラクターに渡されたローカル変数がクラスメンバーをオーバーライドするため、実際には悲しみがあります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;
}

他の値は、このコンストラクターを使用して初期化されていないことに注意してください。それが意図されている場合もあれば、すべてをデフォルト値に設定したい場合もあります。これを明示的に行う必要があります。

さて、これらすべての統計が設定された単一のインスタンスが必要だったようです。実行したいのは、1つのコンストラクター(空のコンストラクター)を使用し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);

または、これらが新しいプレーヤーのデフォルトである場合は、コンストラクターでそれを行うと、覚えておく必要はありません。

それがあなたを始めることを願っています。楽しんで、実験することを恐れないでください。

于 2012-09-15T08:43:15.137 に答える
1

これらのコンストラクターは適切に定義されていません。引数を取りますが、値に対しては何もしません代わりにこれを試してください:

PlayerStatistics::PlayerStatistics(int Experience, int Level)
:
  Experience(Experience),
  Level(Level)
{

}

これは、おおよそ次のようになります。

PlayerStatistics::PlayerStatistics(int Experience, int Level)
{
  this->Experience = Experience;
  this->Level = Level
}

もちろん、他のフィールドも同じように初期化し、未指定のフィールドをデフォルトに設定する必要がありますが、そのアイデアは得られます。

于 2012-09-15T08:30:52.933 に答える
0

コンストラクターは値を設定しません。コンストラクターは任意のパラメーターを持つことができ、それらのパラメーターが同じ名前であるという理由だけでデータメンバーに割り当てられることはありません。

必要なもの:

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) ...は「初期化リスト」であり、「この基本クラスまたはデータメンバーをその値で初期化する」ことを意味します。あなたの場合、値はたまたまデータメンバーと同じ名前を持っていますが、それは問題ありません。コンパイラは、コンテキストからどちらがどちらであるかを判断します。

于 2012-09-15T08:31:08.420 に答える