Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
suxisuxido
記事: 5
登録日時: 12年前

Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#1

投稿記事 by suxisuxido » 12年前

はじめまして、suxisuxidoと申します。

大学でC言語を一年程学んでいます。
私は最近趣味でゲームプログラミング(RPG)を始めました。
DXライブラリを用いるため、使用言語は "C++" , コンパイラは "VC++2010" です。
(OSはWindows7です。)

"ゲームプログラミングの館" をはじめ、様々なサイトや、
"独習C++(書籍)" を参考にしてチビチビと進めていき、以下の3つの状態
『タイトル画面・選択画面("はじめから"や"オプション"などの項目のみ。)・マップ画面(キャラと地形が表示される)』
と、その各状態の遷移(Enterキーを押すと状態が変わっていく)までを実装出来ました。

しかし、
「せっかくC++やるんだから、クラス使わなきゃ!」という軽い考えのもと、
クラスを用いたプログラムに変えていったところ、
どうしても解決しない問題に直面したので、ここで質問する事に致しました。

さて、本題ですが、今私がしたい事は
Characterクラスのメンバ関数(Character_Calculate)の中で、Mapクラスのメンバ関数(WalkOrNot)を呼び出す。
という事です。

実際のコードは以下の通りです。

コード:

/*--- Character.h ---*/
#ifndef DEF_CHARACTER_H
#define DEF_CHARACTER_H

#include "DxLib.h"
#include "stdio.h"
#include "Map.h"
#include "Keyboard.h"

/*--- キャラに関するデータ格納用構造体 ---*/
typedef struct{
	int x;
	int y;
	int image;
	int walk_flag;
	int muki;
}ch_t;

/*--- Characterクラスの定義 ---*/
class Character{
private:

	ch_t syuzinkou;
	int Image[16];

public:

	Character();//コンストラクタ
	~Character();//デストラクタ

	//キャラクタの位置情報を計算
	void Character_Calculate()
	{

		if( syuzinkou.x%32==0 && syuzinkou.y%32==0){     //座標が32で割り切れたら
			syuzinkou.walk_flag = 1;                     //歩くフラグを立てる
			if      ( Keyboard_Get(KEY_INPUT_UP) == 1 )  //上が押されたら
				syuzinkou.muki = 0;                      //上向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_LEFT) == 1 )//左が押されたら
				syuzinkou.muki = 1;                      //左向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_DOWN) == 1 )//下が押されたら
				syuzinkou.muki = 2;                      //下向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_RIGHT) == 1 )//右が押されたら
				syuzinkou.muki = 3;                       //右向きフラグを立てる
			else//もし何も押されてなかったら
				syuzinkou.walk_flag = 0;//歩かないフラグを立てる

			if(syuzinkou.walk_flag == 1)//歩くフラグが立ってれば
/*--- WalkOrNot の所で error C3861: 'WalkOrNot': 識別子が見つかりませんでした. とビルドエラーになります。---*/
				if(WalkOrNot(syuzinkou.x,syuzinkou.y,syuzinkou.muki) == 1)//歩けるマスか判定
					syuzinkou.walk_flag = 0;//歩かないフラグを立てる
		}

		if( syuzinkou.walk_flag == 1 ){                 //歩くフラグが立っていたら
			if     (syuzinkou.muki == 0) syuzinkou.y-=4;//上向きならy座標減少
			else if(syuzinkou.muki == 1) syuzinkou.x-=4;//左向きならx座標減少
			else if(syuzinkou.muki == 2) syuzinkou.y+=4;//下向きならy座標増加
			else if(syuzinkou.muki == 3) syuzinkou.x+=4;//右向きならx座標増加
		}
	}

	//キャラクタを描画
	void Character_Draw(){
		syuzinkou.image = Image[(syuzinkou.x%32 + syuzinkou.y%32) / 8 + syuzinkou.muki*4];
		DrawGraph( syuzinkou.x , syuzinkou.y , syuzinkou.image , TRUE );
	}


};

#endif

コード:

/*--- Character.cpp ---*/
#include "DxLib.h"
#include "Character.h"



/*--- Characterクラスの実装 ---*/

//コンストラクタ
Character::Character(){
	LoadDivGraph( "syuzinkou.png",16,4,4,32,32,Image);
	syuzinkou.x = 320;
	syuzinkou.y = 320;
	syuzinkou.walk_flag = 0;
	syuzinkou.muki = 3;
}

Character::~Character(){

}

コード:

/*--- Map.h ---*/
#ifndef DEF_MAP_H
#define DEF_MAP_H

#include "DxLib.h"
#include "stdio.h"
#include "Character.h"

#define SIBAHU     0
#define SUNA       1
#define KIRIKABU 101

/*--- Mapクラスの定義 ---*/
class Map{
private:

	int map1[16][20];
	int mapimage[256];

public:

	/*--- マップのあたり判定 ---*/
	int WalkOrNot(int x,int y,int muki)
	{
		if(muki==0)//上向きなら
			if(map1[y/32-1][x/32] < 0)//キャラの目の前のマスが1(進行不可)だったら
				return 1;//1が帰ったらエラー
		if(muki==1)//左向きなら
			if(map1[y/32][x/32-1] < 0)
				return 1;
		if(muki==2)//下向きなら
			if(map1[y/32+1][x/32] < 0)
				return 1;
		if(muki==3)//右向きなら
			if(map1[y/32][x/32+1] < 0)
				return 1;
		//どれにも当てはまらない(進行方向が0)なら
		return 0;//0が帰ったら歩ける
	}

	/*--- マップの描画 ---*/
	void Map_Draw()
	{
		for(int i=0;i<16;i++){
			for(int j=0;j<20;j++){
				if(map1[i][j]==0)  DrawGraph(j*32,i*32,mapimage[SIBAHU],FALSE);
				if(map1[i][j]==1){
					DrawGraph(j*32,i*32,mapimage[SIBAHU],FALSE);//一旦芝生を描画してから
					DrawGraph(j*32,i*32,mapimage[SUNA],FALSE);//その上に砂を描画
				}
				if(map1[i][j]==-35){
					DrawGraph(j*32,i*32,mapimage[SIBAHU],FALSE);//上と同じ
					DrawGraph(j*32,i*32,mapimage[KIRIKABU],TRUE);
				}
			}
		}
	}


	Map(); //コンストラクタ
	~Map();//デストラクタ

};

#endif

コード:

/*--- Map.cpp ---*/
#include "Map.h"
#include "stdio.h"
#include "DxLib.h"

/*--- Mapクラスの実装 ---*/

/*--- コンストラクタ ---*/
Map::Map(){

	//ローカル変数で初期値を設定
	static int temp1[16][20] = {//サイズが大きくなるのでstatic
		{ -35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35,-35 },
		{ -35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35 },
		{ -35,-35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35 },
		{ -35,-35,-35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35 },
		{ -35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35,-35 },
		{ -35,-35,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35,-35 },
		{ -35,-35,0,1,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35,-35 },
		{ 1,0,0,1,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35,-35 },
		{ 0,-35,-35,-35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-35,-35,-35,-35,-35 },
		{ 0,-35,-35,-35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ -35,-35,-35,-35,-35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ 1,1,1,1,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ 0,1,0,1,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ 1,1,1,0,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ 1,1,1,1,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
		{ 1,1,1,1,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1 },
	};

	//メンバ変数にコピー
	memcpy(map1 , temp1, sizeof temp1);

	//マップチップをロード
	LoadDivGraph( "map_c02.png",256,8,32,32,32,mapimage);

}

/*--- デストラクタ ---*/
Map::~Map(){}
以上、今直面している問題に関係があると思われるコード達です。
Keyboard.h(キーの入力状態を得るための関数等を含んだヘッダ)やmain.cppや画像ファイルは、
直接この問題には関係が無いと思うので載せません*1。
*1これらが無いと皆さんのPCでコンパイル出来ないので、要望があれば載せます。
必ず全てのソースを載せる事が常識なのでしたら、すみません。

CharacterクラスのCharacter_Calculate()関数の中で、キャラとマップのあたり判定を得るために
MapクラスのWalkOrNot(int x,int y,int muki)を呼び出したいのですが、上手くいきません。

ちなみに当然(?)ですが、クラスを使った実装に変更する前は、
ちゃんと動作していました(当たり判定も)。

フレンドや継承など、クラスに関して調べると色々出てくるのですが、
それらを用いようとしても上手くいきません。(現在のコードはそれらを試す前のものにしました)


何かと至らないところが多いと思いますが、よろしくお願いいたします。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#2

投稿記事 by beatle » 12年前

クラスのメンバ関数を呼び出すためには、クラスのインスタンスが必要です。
例えば

コード:

class A {
public:
    int foo();
};
というクラス定義があった場合、

コード:

A a;
a.foo();
のようには呼び出せますが、

コード:

A::foo();
foo();
というような呼び出し方は両方共エラーです。
ただし、fooメンバ関数をstatic関数にすれば、A::foo()という呼び出し方は可能です。
それでもfoo()という呼び出し方はできません。fooはグローバル関数ではないのですから。

suxisuxido
記事: 5
登録日時: 12年前

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#3

投稿記事 by suxisuxido » 12年前

beatleさんへ。

返信ありがとうございます。
beatle さんが書きました:クラスのメンバ関数を呼び出すためには、クラスのインスタンスが必要です。
例えば

コード:

class A {
public:
int foo();
};
というクラス定義があった場合、

コード:

A a;
a.foo();
のようには呼び出せますが、
この意見に基づいて、
Character.hを変更してみました(下記の通り)

コード:

/*--- 省略 ---*/
Map c;/*パターン1*/
/*--- Characterクラスの定義 ---*/
class Character{
private:

	ch_t syuzinkou;
	int Image[16];

public:

	Map c;/*パターン2*/
	Character();//コンストラクタ
	~Character();//デストラクタ

	//キャラクタの位置情報を計算
	void Character_Calculate()
	{

		Map c;/*パターン3*/

		if( syuzinkou.x%32==0 && syuzinkou.y%32==0){     //座標が32で割り切れたら
			syuzinkou.walk_flag = 1;                     //歩くフラグを立てる
			if      ( Keyboard_Get(KEY_INPUT_UP) == 1 )  //上が押されたら
				syuzinkou.muki = 0;                      //上向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_LEFT) == 1 )//左が押されたら
				syuzinkou.muki = 1;                      //左向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_DOWN) == 1 )//下が押されたら
				syuzinkou.muki = 2;                      //下向きフラグを立てる
			else if ( Keyboard_Get(KEY_INPUT_RIGHT) == 1 )//右が押されたら
				syuzinkou.muki = 3;                       //右向きフラグを立てる
			else//もし何も押されてなかったら
				syuzinkou.walk_flag = 0;//歩かないフラグを立てる

			if(syuzinkou.walk_flag == 1)//歩くフラグが立ってれば
				if(c.WalkOrNot(syuzinkou.x,syuzinkou.y,syuzinkou.muki) == 1)//歩けるマスか判定
					syuzinkou.walk_flag = 0;//歩かないフラグを立てる
		}

		if( syuzinkou.walk_flag == 1 ){                 //歩くフラグが立っていたら
			if     (syuzinkou.muki == 0) syuzinkou.y-=4;//上向きならy座標減少
			else if(syuzinkou.muki == 1) syuzinkou.x-=4;//左向きならx座標減少
			else if(syuzinkou.muki == 2) syuzinkou.y+=4;//下向きならy座標増加
			else if(syuzinkou.muki == 3) syuzinkou.x+=4;//右向きならx座標増加
		}
	}
/*--- 以下略 ---*/
上記のように、3つの位置のパターンで試してみたのですが(もちろんビルド時、3つの内2つはコメントアウトしています。)
どれもダメで、このようなエラーが出ます。
構文エラー : ';' が、識別子 'c' の前に必要です。
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません
'c' : 定義されていない識別子です。
'.WalkOrNot' の左側はクラス、構造体、共用体でなければなりません


私の解釈が間違っているのでしょうか?

nil
記事: 428
登録日時: 12年前

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#4

投稿記事 by nil » 12年前

Mapクラスを定義したヘッダーをインクルードしましたか?

suxisuxido
記事: 5
登録日時: 12年前

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#5

投稿記事 by suxisuxido » 12年前

涼雅さんへ。

返信ありがとうございます。
涼雅 さんが書きました:Mapクラスを定義したヘッダーをインクルードしましたか?
上に書いてある通り、しっかりとincludeしています。
いや、あの include "Map.h" が何か技術的に間違っているとすれば、
私はとんでもない勘違いをしていると思うので、ご指摘ください。

でも、大丈夫なはずです。

beatle
記事: 1281
登録日時: 12年前
住所: 埼玉
連絡を取る:

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#6

投稿記事 by beatle » 12年前

Map.hとCharacter.hが相互にincludeしあっているために、Character.hの前方でMap.hがインクルードされていない(というより、インクルードガードによって中身が読み込まれない)のでしょう。
これはインクルードガードが上手く働いている結果ですね。

オススメの解決法は、ヘッダファイルにメソッドの中身を定義しないことです。ヘッダファイルに対応するcppファイルを作り、そこでメソッドを定義しましょう。

suxisuxido
記事: 5
登録日時: 12年前

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#7

投稿記事 by suxisuxido » 12年前

beatleさんへ。

返信ありがとうございます。
beatle さんが書きました:Map.hとCharacter.hが相互にincludeしあっているために、Character.hの前方でMap.hがインクルードされていない(というより、インクルードガードによって中身が読み込まれない)のでしょう。
これはインクルードガードが上手く働いている結果ですね。

オススメの解決法は、ヘッダファイルにメソッドの中身を定義しないことです。ヘッダファイルに対応するcppファイルを作り、そこでメソッドを定義しましょう。
ご指摘の通り(?)、Map.h側の「include "Character.h"」を消したところ、無事コンパイルに通り、思い通りの動作を致しました。

私はとんでもない勘違いをしていた・・・・といいますか、インクルードガードの本質を理解していなかったようです。
していなかった、といいますか、今もまだ理解出来てないかもしれません・・・。

ただ”二重読み込みを防止する”という部分ばかりに目が行ってしまって、
ヘッダをincludeした時点で、”そのヘッダのclassと、そのヘッダがincludeしているヘッダのclass”も定義されてしまうという事に
気づきませんでした。
ただガードしたからこれでOK!!!というわけじゃないのですね、自分の考えが甘かったです。

それから、今考えると、Map.h側でCharacter.hをincludeする意味が全くありませんでしたね・・・。

さっそく今から、hファイル内ではなくcppファイル内でメソッドを定義してみようと思います。

本当にありがとうございました、これで解決です。

非常にピンポイントなご指摘をしていただけた事に、感謝しています。



涼雅さんへ。

涼雅さんの言わんとしていた事を理解できずに申し訳ありません。
まさかこんなことが(と言ったら失礼かもしれませんが)エラーの原因になってるとは夢にも思いませんでした。

本当にありがとうございました。

suxisuxido
記事: 5
登録日時: 12年前

Re: Aクラスのメンバ関数内でBクラスのメンバ関数を読み込みたい!

#8

投稿記事 by suxisuxido » 12年前

あ、解決にし忘れていました。
すみません。

閉鎖

“C言語何でも質問掲示板” へ戻る