複数のファイルで自作クラスを使いたいのですが...

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

複数のファイルで自作クラスを使いたいのですが...

#1

投稿記事 by onehst » 9年前

初めての投稿です。初心者なので凄い初歩的な質問かも知れませんがご了承ください。

今、2Dのアクションゲームを作っているのですが、自分で作ったクラス(CじゃなくてC++の範囲ですが...)のインスタンスを
複数のファイルで定義したい場合の処理が分からず困っています。2重定義防止文?ってのをかいてもエラーが吐かれました。

具体的には
Class.h ←自作のヘッダ
#ifndef CLASS_H_INCLUDED_
#define CLASS_H_INCLUDED_
#include "define.h"
#include "DxLib.h"

//敵のクラス
class Enemy{
public :
double x,y; //敵の座標
double speed,shotspeed; //移動速度と玉の速さ
double Shot_X, Shot_Y; //玉の現在位置
double ShotDif_X,ShotDif_Y; //玉の進む方向
int ShotTime; //玉の撃つ間隔
bool ShotFlag;

int timing,turn; //方向変換の間隔と方向
Enemy();
void Attack(int Time);
};

Enemy::Enemy(){
x=0.0; y=0.0;
speed=1.0; shotspeed=2.5;
Shot_X=-100; Shot_Y=-100; //撃つ弾の座標
ShotFlag=true; //敵の攻撃用
timing=GetRand(2)+1; //方向変換の間隔
ShotTime=0; //撃つ間隔を制限する
}

void Enemy::Attack(int Time){ //敵の攻撃メソッド
extern int HandleShot[12]; //玉の画像
extern int Handle[2];//玉の発射音

if(GetRand(40)==1&&ShotFlag){ //まず確率調整をここでする
ShotFlag=false; ShotTime=0;
Shot_X=x; Shot_Y=y; //今敵のいる位置を初期座標とする
PlaySoundMem( Handle[1], DX_PLAYTYPE_BACK ); //玉の発射音の再生
switch(turn){ //方向によって玉の有効範囲を決める
case 0: ShotDif_X=0; ShotDif_Y=shotspeed; break; //下
case 1: ShotDif_X=-shotspeed; ShotDif_Y=0; break; //左
case 2: ShotDif_X=shotspeed; ShotDif_Y=0; break; //右
case 3: ShotDif_X=0; ShotDif_Y=-shotspeed; break; //上
}

}
//玉の描画(範囲内にあるなら描画をする)
if( Shot_X >= FIELD_MIN_X && Shot_X <= FIELD_MAX_X && Shot_Y >= FIELD_MIN_Y && Shot_Y <= FIELD_MAX_Y){
int img=(Time%24)/8; //玉の画像を巡回
DrawGraph(40+Shot_X,40+Shot_Y,HandleShot[img],TRUE);
Shot_X+=ShotDif_X; Shot_Y+=ShotDif_Y;
}else if(ShotTime>=120){ //打ち終わってから2秒間は打たない
ShotFlag=true;
}
ShotTime++;
}


//プレイヤーのクラス
class Player{
public :
double x,y,speed; //座標、スピード
int lives; //残機
int Attack,Difence; //攻撃力、防御力
int plus,route; //方向と止まる処理用
int score; //スコア
Player();
};

Player::Player(){
x=150; y=300;
speed=1;
lives=2; //初期残機は2
Attack=4;Difence=2; //値を何にするかは未定
plus = 0; route=0;
score=120;

}

#endif

//-----------------------------------------------Class.h終わり--------------------------------------------------//
draw.cpp //描画を行なうソースファイル

#include "DxLib.h"
#include "define.h"
#include "Class.h"
#include <math.h>

static Player player;
static Enemy ene[5]; //敵のインスタンスを生成

//マップの壁画
void mapdraw(){

extern int HandleMap[2];

//ボードの作成
DrawModiGraph(0,0,700,0,700,500,0,500,HandleMap[1],TRUE);
//ステージマップの作成
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
DrawGraph(20+40*i,10+40*j,HandleMap[0],TRUE);
}
}

}

//キャラとキャラ周りの壁画
void boydraw(int Time){

extern int Handleboy[12];
int img; //画像を巡回させる

//移動
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ){
player.plus=3; player.route=1;
}else if(CheckHitKey( KEY_INPUT_RIGHT ) == 1 ){
player.plus=6; player.route=2;
}else if(CheckHitKey( KEY_INPUT_UP ) == 1){
player.plus=9; player.route=3;
}else if(CheckHitKey( KEY_INPUT_DOWN ) == 1){
player.plus=0; player.route=0;
}else player.route=4;

//キーによって歩く方向の処理をする
switch(player.route){
case 0: if(player.y<=FIELD_MAX_Y) player.y+=player.speed; break;
case 1: if(player.x>=FIELD_MIN_X)player.x-=player.speed; break;
case 2: if(player.x<=FIELD_MAX_X)player.x+=player.speed; break;
case 3: if(player.y>=FIELD_MIN_Y) player.y-=player.speed; break;
default: break;
}

//歩行モーションを分ける

if(player.route!=4)
img=(Time%24)/8+player.plus; //動いているとき
else
img=player.plus; //止まってる時

DrawGraph(40+player.x,40+player.y,Handleboy[img],TRUE); //描画でっせ

//残機の表示
for(int i=0; i<=player.lives; i++){
DrawRotaGraph(470+30*i,140,0.8f,0.0f,Handleboy[0],TRUE);
}



}

//敵の描画
void Enemydraw(int Time){
extern int HandleEnemy[12]; //敵の画像

static int plus[ENEMY_NUMBER]={0}; //方向を決める

for(int i=0;i<ENEMY_NUMBER;i++){

if(Time%(ene.timing*45)==0){ //方向変換
switch(GetRand(3)){
case 0: plus=0; ene.turn=0; break;
case 1: plus=3; ene.turn=1; break;
case 2: plus=6; ene.turn=2; break;
case 3: plus=9; ene.turn=3; break;
}
}

//移動可能範囲を絞る
switch(plus){
case 0: if(ene[i].y<=FIELD_MAX_Y) ene[i].y+=ene[i].speed; break;
case 3: if(ene[i].x>=FIELD_MIN_X)ene[i].x-=ene[i].speed; break;
case 6: if(ene[i].x<=FIELD_MAX_X)ene[i].x+=ene[i].speed; break;
case 9: if(ene[i].y>=FIELD_MIN_Y) ene[i].y-=ene[i].speed; break;
}

//画像を巡回させて描画
int img=(Time%24)/8+plus[i];
DrawGraph(40+ene[i].x,40+ene[i].y,HandleEnemy[img],TRUE);
//方向変換するタイミングを変える
ene[i].timing=GetRand(2)+1;
//攻撃を先にやる?(テスト)
ene[i].Attack(Time);
}

}

//メニューの壁画
void Menudraw(int Time){
extern int Font00,Font01,Font02;
extern int HandleNum[10];
static int Englishnum[12]={13,14,22,29,2,17,4,0,19,8,13,6};
extern int image[30];
extern int HandleItem[96];


//NOW CREATING
for(int i=0;i<12;i++){
DrawRotaGraph(20+30*(i+1),400+8*(sin(PI*(Time+3*i)/30)+1)/2,1.5f,0.0f,image[Englishnum[i]],TRUE);
}


//アイテムを表示(テスト)
DrawModiGraph(216+20*cos(PI+(PI*Time/120)),200,216+20*cos(PI*Time/120),
200,216+20*cos(PI*Time/120),240,216+20*cos(PI+(PI*Time/120)),240,HandleItem[4],TRUE);

//文字(タイトルと作成者名)
DrawStringToHandle( 420, 20, "Words", GetColor(255,255,255), Font02 );
DrawStringToHandle( 480, 60, "Puzzle", GetColor(255,255,255), Font02 );
DrawStringToHandle( 420, 360, "Created by", GetColor(255,255,0), Font01 );
DrawStringToHandle( 440, 400, "High Stone.", GetColor(255,255,0), Font01 );

//スコアとステータスボードの表示
DrawStringToHandle( 400, 100, "得点:", GetColor(255,255,255), Font00 );
DrawStringToHandle( 400, 130, "残機:", GetColor(255,255,255), Font00 );
DrawStringToHandle( 400, 160, "レベル:", GetColor(255,255,255), Font00 );
DrawStringToHandle( 400, 190, "ステータス", GetColor(255,255,255), Font00 );

//スコアの表示
int score=player.score;

for(int i=0; score>=1; i++){
DrawRotaGraph(570-20*i,110,1.2f,0.0f,HandleNum[score%10],TRUE);
score/=10;
}

//ステータスの表示(1桁なら上三行はいらない)
int Attack=player.Attack;
int Difence=player.Difence;
int Speed=player.speed;

DrawRotaGraph(440,275,1.2f,0.0f,HandleNum[Attack%10],TRUE); //攻撃力
DrawRotaGraph(500,275,1.2f,0.0f,HandleNum[Difence%10],TRUE); //防御力
DrawRotaGraph(560,275,1.2f,0.0f,HandleNum[Speed%10],TRUE); //スピード


//レベルの表示
DrawFormatString(565,165,GetColor(0,0,0),"1");
//ステータス画像の表示
DrawRotaGraph(440,240,1.6f,0,HandleItem[1],TRUE); //攻撃力
DrawRotaGraph(500,240,1.6f,0,HandleItem[13],TRUE); //防御力
DrawRotaGraph(560,240,1.6f,0,HandleItem[21],TRUE); //スピード

//テスト用
player.score++;
}

//------------------------------------------------------draw.cpp 終わり---------------------------------------------------------//
judge.cpp ← あたり判定を定義する まだ全然書いてない
#include"DxLib.h"
#include"Class.h" ←これを書くとエラーになる

//当たり判定は4種類

//敵の弾がプレイヤーにヒット
void EneHitPlayer(){

}

//自分がアイテムにヒット(ゲット)
void PlayerGetItem(){

}

//自分の弾が敵にヒット
void PlayerHitEne(){

}

//自分の弾が敵の弾にヒット(相殺)
void bulletHit(){

}
//---------------------------------judge.cpp 終わり--------------------------------------------//
エラー内容は次のようになります。
1>judge.obj : error LNK2005: "public: __thiscall Enemy::Enemy(void)" (??0Enemy@@QAE@XZ) は既に draw.obj で定義されています。
1>judge.obj : error LNK2005: "public: void __thiscall Enemy::Attack(int)" (?Attack@Enemy@@QAEXH@Z) は既に draw.obj で定義されています。
1>judge.obj : error LNK2005: "public: __thiscall Player::Player(void)" (??0Player@@QAE@XZ) は既に draw.obj で定義されています。
1>C:\Users\Kazuki\Desktop\GameProg2\Debug\GameProg2.exe : fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。


おそらく二重定義になっているのだと思うのですが.....
どなたかこれの解決方法または、複数のcppファイルで自分の作ったクラスを定義する方法を教えて欲しいです。

長文失礼いたしました。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 複数のファイルで自作クラスを使いたいのですが...

#2

投稿記事 by YuO » 9年前

大雑把に書くと (標準規格とかの話は無視します),ヘッダファイルにはメモリの確保を伴わない物を書きます。
この例外はinline関数 (クラス定義内やtemplateによる暗黙のinline関数を含む) です。
関数や変数の定義はメモリを確保するので,ヘッダファイルに書いてはいけません。

メモリの確保を伴う物は,Class.cppのようなソースファイルに記述します。

onehst
記事: 14
登録日時: 9年前
住所: 東京都

Re: 複数のファイルで自作クラスを使いたいのですが...

#3

投稿記事 by onehst » 9年前

回答ありがとうございます!!
おかげさまで解決いたしました!!ありがとうございます!!

閉鎖

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