「教えて!ピックアップ」リリース!

こんにちは。私は現在C++を学習中の者です。
現在、
「実例で学ぶゲームAIプログラミング」(オライリージャパン)
という本で学習をしているのですが、試しに組んでみた非常に簡単なプログラムでエラーが出て、原因が分からず困っています。

初歩の部分で恐縮なのですが、クラス自身に状態遷移の機能を持たせようとしているようです。
以下のコードは実際にエラーが出たコードです。

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;


class Troll;

class State{
public:
virtual void Execute(Troll* troll) = 0;
};


class Troll{
State* m_pCurrentState;
public:
void Update(){ m_pCurrentState->Execute(this); }
void ChangeState(State* pNewState){ delete m_pCurrentState; m_pCurrentState = pNewState; }


bool isSafe();
bool isThreatened();
void Snore(){ cout << " I am sleeping zzz... " << endl;}
void MoveAwayFromEnemy(){ cout << " Run Away!!" << endl;}
};

bool Troll::isSafe(){
int safe = (int)((rand() / ((double)RAND_MAX+1.0f)) * 10);
if(safe >= 5) return true;
else return false;
}

bool Troll::isThreatened(){
int threat = (int)((rand()/((double)RAND_MAX+1.0f))*10);
if(threat >= 3) return true;
else return false;
}

class State_Sleep;

class State_Runaway: public State{
void Execute(Troll* troll){
if(troll->isSafe()){troll->ChangeState(new State_Sleep());}      ←エラー
else{troll->MoveAwayFromEnemy();}
}
};

class State_Sleep : public State{
public:
void Execute(Troll* troll){
if(troll->isThreatened()){ troll->ChangeState(new State_Runaway());}
else{ troll->Snore();}
}
};

main以下は書いていません。
この中で、State,State_Runaway,State_Sleep,は本の丸写しです。
また、Trollの中のpublic以下の、スペースで区切っている部分より上も、丸写しです。スペース以下は動かす為に必要と思い適当につくってみました。
(本では、「このようなのを使えば上手くできるよ」というかんじで、上記の様に部分的に載っていて、一つの完成したコードはありませんでした。)

上記コードの、エラー、と書いた部分で、「クラス、構造体、共用体に既定のコンストラクタがありません。」のエラーが出ます。

自分なりに意味も調べてみて、コンストラクタを定義してるのに、デフォルトコンストラクタを呼び出そうとしてる時に起こるエラーと理解したのですが、上記のコードにどう関わってくるのか良くわかりませんでした。

あとその部分で、new State_Runaway()としていますが、これも意味がわかりませんでした。
new State_Runaway、ではないのでしょうか。
そうしても同じエラーが出ましたが…。


継承クラス等を使うのが初めてなので、かなり初歩的なところでつまずいてる気がするのですが、どういうことかわかる方がいらっしゃいましたらお教え頂ければ幸いです。

A 回答 (1件)

ここでは継承は全く関係ありません.


例えば「new State_Sleep()」って「クラス State_Sleep のデフォルトコンストラクタ」を呼び出すよね.
ちなみにコンストラクタを呼び出すためにはクラスを定義しておく必要があります.

この回答への補足

返答が遅くなってしまいましたが、ありがとうございます!!
ご指摘の通り、Executeの中身をクラスの外、定義が必要なクラスの下に移す事で解決しました。
また、new State()とnew State は表記が違うだけで同じ意味なのですね。
恥ずかしい質問でした。もっと基礎を勉強すべきでした。

少し疑問に思った事があるので追加で質問させて頂いても宜しいでしょうか。
この場合の様に、上から読んでいって、定義から先に書くようにする以外方法はないのでしょうか?
例えば上記コードの上の方で、

class Troll;

class State{
public:
virtual void Execute(Troll* troll) = 0;
};

という部分があります。
私は一度、Trollクラスはこの下で定義してるから…、とコンパイルし、(当然)失敗して、class Troll; という一文を後から付け加えました。
今回の質問も、同じような事で詰まっていたようです。

ですが、主観ですが、class Troll; とわざわざ書くのは醜いコード、というか、C++のプロの方から見れば「そんな事書かなくても別の方法があるのに。」というような気がしてなりません。
このclass Troll;のように、どんな事があっても、使う前(上)で定義しておいて、コンパイラに教えてあげなくてはいけないのでしょうか??
何か抜け道等は無いのでしょうか?

ちょっと気になるので新しく質問させて頂きました。
回答の締め切り、ポイントの付与、をもう少しお待ちください。
もちろん回答頂けずとも適度に締め切って、あらためてポイント付与とお礼させて頂きます。

補足日時:2009/12/11 01:35
    • good
    • 0
この回答へのお礼

おかげさまで質問で詰まっていた部分が解決いたしました。
本当にありがとうございました。

お礼日時:2009/12/12 16:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング