どこかで既に定義されている

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Chalaza

どこかで既に定義されている

#1

投稿記事 by Chalaza » 14年前

RPGを制作していて、表示する物体をひとまとめにしたObjectという構造体配列をFMap.hというヘッダファイルに作って、
それをMain.cppを通してポインタで他のcppから使用したりできるようにしたかったのですが、
main.obj : error LNK2005: "struct ObjectData_t * ObjectData" (?ObjectData@@3PAUObjectData_t@@A) は既に FMap.obj で定義されています。
というエラーがでて困っています。
構造体以外の部分で定義したつもりはないのですが、どこでエラーに引っ掛かっているのでしょうか?

FMap.h

コード:

#ifndef DEF_FMAP_H //二重include防止

#define DEF_FMAP_H

// 描画順並べ替え用物体構造体
typedef struct {
	int X;
	int Y;
	int DrawX;
	int DrawY;
	int Img;
}ObjectData_t;
// 物体構造体の実体
ObjectData_t ObjectData[4];

//マップ初期化
void FMap_Initialize();

//オブジェクト位置計算
void FMAP_Object(FPlayer_t FPlayer, ObjectData_t Objectdata);

//マップ描画
void FMap_Draw();

//マップスクロール
void FMap_Scroll( FPlayer_t *FPlayer );


#endif 

FMap.cpp

コード:

#include "DxLib.h"
#include "FPlayer.h"
#include "FMap.h"

//MAP共通
#define SCREEN_WIDTH 512
#define SCREEN_HEIGHT 384
int CameraX,CameraY;


int Chip[10];//マップチップ画像用
int Kagu[10];//マップ家具画像用

void FMap_Initialize()//フィールドマップ初期化
{
	int CaffeYuka = LoadGraph("Image/Map/Yuka/CaffeYuka.png");
	int CaffeKabe1LEFT = LoadGraph("Image/Map/Kabe/Caffe1LEFT.png");
	int CaffeKabe1RIGHT = LoadGraph("Image/Map/Kabe/Caffe1RIGHT.png");
	int CaffeKabe2LEFT = LoadGraph("Image/Map/Kabe/Caffe2LEFT.png");
	int CaffeKabe2RIGHT = LoadGraph("Image/Map/Kabe/Caffe2RIGHT.png");

	int Syokubutu1 = LoadGraph("Image/Map/Kagu/Syokubutu1.png");
	int Gomibako = LoadGraph("Image/Map/Kagu/Gomibako.png");
	int Table1 = LoadGraph("Image/Map/Kagu/Table1.png");

	Chip[1] = CaffeYuka;
	Chip[6] = CaffeKabe1LEFT;
	Chip[7] = CaffeKabe1RIGHT;
	Chip[8] = CaffeKabe2LEFT;
	Chip[9] = CaffeKabe2RIGHT;

	Kagu[1] = Syokubutu1;
	Kagu[2] = Gomibako;
	Kagu[3] = Table1;


}


//マップ1
#define MAP_HEIGHT 12
#define MAP_WIDTH 12
#define STAGE_HEIGHT 15
#define STAGE_WIDTH 15
int IramudukiMAP[MAP_HEIGHT][MAP_WIDTH] = //壁と床用マップデータ
{

                    {0,9,9,9,9,9,9,9,9,9,9,0,},
                   {8,0,7,7,7,7,7,7,7,7,7,7,},
                  {8,6,1,1,1,1,1,1,1,1,1,1,},
                 {8,6,1,1,1,1,1,1,1,1,1,1,},
                {8,6,1,1,1,1,1,1,1,1,1,1,},
               {8,6,1,1,1,1,1,1,1,1,1,1,},
              {8,6,1,1,1,1,1,1,1,1,1,1,},
             {8,6,1,1,1,1,1,1,1,1,1,1,},
            {8,6,1,1,1,1,1,1,1,1,1,1,},
           {8,6,1,1,1,1,1,1,1,1,1,1,},
		  {8,6,1,1,1,1,1,1,1,1,1,1,},
	     {0,6,1,1,1,1,1,1,1,1,1,1,},

};

int IramudukiKAGU[MAP_HEIGHT][MAP_WIDTH] = //家具用マップデータ
{

                    {0,0,0,0,0,0,0,0,0,0,0,0,},
                   {0,0,0,0,0,0,0,0,0,0,0,0,},
                  {0,0,0,0,0,0,0,0,0,0,0,0,},
                 {0,0,0,0,0,0,0,3,0,0,0,0,},
                {0,0,0,0,0,0,0,0,0,0,0,0,},
               {0,0,0,0,0,0,0,0,0,0,0,0,},
              {0,0,0,0,0,0,0,0,0,0,0,0,},
             {0,0,0,0,0,0,0,0,0,0,0,0,},
            {0,0,0,0,0,0,0,0,0,0,0,1,},
           {0,0,0,0,0,0,0,0,0,0,0,0,},
          {0,0,0,0,0,0,0,0,0,0,0,0,},
         {0,0,0,0,0,0,0,0,0,0,0,2,},

};

void FMAP_Object(FPlayer_t FPlayer, ObjectData_t Objectdata){//オブジェクト構造体に物体の座標を代入
	ObjectData[0].X = FPlayer.X;	//プレイヤーのXY座標
	ObjectData[0].Y = FPlayer.Y;
	ObjectData[0].DrawX = FPlayer.ViewX;
	ObjectData[0].DrawY = FPlayer.ViewY;
	ObjectData[1].Img = Kagu[1];	//植物の画像
	ObjectData[2].Img = Kagu[2];	//ゴミ箱の画像
	ObjectData[3].Img = Kagu[3];	//テーブルの画像

	//家具用マップデータから置くXY座標を計算
	int x,y;
	for(y=0;y<MAP_HEIGHT;++y) 
	{
		for(x=0;x<MAP_WIDTH;++x)
		{
			if(IramudukiKAGU[y][x]!=0 && IramudukiKAGU[y][x]<=3){
				ObjectData[(IramudukiKAGU[y][x])].DrawX = 24*12+((12-y)*(48/2)+(x*24)-24-CameraX);
				ObjectData[(IramudukiKAGU[y][x])].DrawY = 12*12+((x+y)*12-CameraY);
			}
		}
	}
}

//オブジェクトのY座標比較関数
int int_cmp(const ObjectData_t **a, const ObjectData_t **b)
{
    if ((*a)->DrawY < (*b)->DrawY)
        return (-1);
    else if ((*a)->DrawY > (*b)->DrawY)
        return (1);
    return (0);
}

void FMap_Draw()//マップ描画
{
	int x,y;

	for(y=0;y<MAP_HEIGHT;++y) 
	{
		for(x=0;x<MAP_WIDTH;++x)
		{
			if(IramudukiMAP[y][x]!=0){
				DrawGraph(24*12+((12-y)*(48/2)+(x*24)-24-CameraX),12*12+((x+y)*12-CameraY),Chip[(IramudukiMAP[y][x])],TRUE); //マップ描画
			}
		}
	}
	
	//物体を奥から描画するように並び替えて描画する
	    int  i;
    ObjectData_t *SortArray[2] = { &ObjectData[0], &ObjectData[1]};
    int  nx = sizeof(SortArray) / sizeof(SortArray[0]);     // 配列の要素数
 
    qsort(SortArray, nx, sizeof(ObjectData_t*), (int(*)(const void*, const void*))int_cmp);//ソートする
 
    for (i = 0; i < nx; i++)
        DrawGraph(192+SortArray[i]->DrawX-CameraX,96+SortArray[i]->DrawY-CameraY,SortArray[i]->Img,TRUE);//物体描画

}

void FMap_Scroll( FPlayer_t *FPlayer)//マップスクロール
{
	CameraX = FPlayer->X - SCREEN_WIDTH/2 + 40;
	//ステージのスクロール
	if(CameraX < 0)CameraX = 0;
	if(CameraX > (MAP_WIDTH*2*48)-SCREEN_WIDTH) CameraX = (MAP_WIDTH*2*48)-SCREEN_WIDTH;

	FPlayer->ViewX = FPlayer->X - CameraX;

	CameraY = FPlayer->Y - SCREEN_HEIGHT/2 + 40;
	//ステージのスクロール
	if(CameraY < 0)CameraY = 0;
	if(CameraY > (MAP_HEIGHT*2*12)-MAP_HEIGHT) CameraY = (MAP_HEIGHT*2*12)-MAP_HEIGHT;

	FPlayer->ViewY = FPlayer->Y - CameraY;
}
main.cpp

コード:

#include "DxLib.h"
#include "FPlayer.h"
#include "Keyboard.h"
#include "FMap.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	SetMainWindowText("RPG");
	ChangeWindowMode(TRUE);
	SetGraphMode(480,360,32);
	if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	//ジョイパ使用
	int GetJoypadInputState( int InputType );

	InputCount_t InputCount;
	FPlayer_t FPlayer;
	ObjectData_t ObjectData;

	FPlayer_Initialize( &FPlayer );	//Fプレイヤー初期化
	FMap_Initialize();

	while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){

		Keyboard_Update();	//キーボード使用
		Input_Count(&InputCount);//入力時間をカウントに

		FPlayer_Calc( &FPlayer, &InputCount);	//Fプレイヤー計算
		FMAP_Object( FPlayer , ObjectData);		//オブジェクト位置計算
		FMap_Scroll( &FPlayer );	//Fマップスクロール

		FMap_Draw();		//Fマップ描画
		FPlayer_Draw( FPlayer );	//Fプレイヤー描画
	}

	FPlayer_Finalize( FPlayer );  // 終了処理

        DxLib_End();
        return 0;
}

box
記事: 2002
登録日時: 15年前

Re: どこかで既に定義されている

#2

投稿記事 by box » 14年前

main.cpp の17行目の存在意義を教えてください。
また、FMAP_Object() の第2引数の型は正しいでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: どこかで既に定義されている

#3

投稿記事 by ISLe » 14年前

インクルードガードは、同じソースファイルで繰り返しインクルードされて多重定義にならないようにするものです。
異なるソースファイルであればそれぞれインクルードされます。
なので、FMap.hの
ObjectData_t ObjectData[4];
は、FMap.cpp、main.cppのそれぞれに挿し込まれるので両方で定義されていることになります。

FMap.cppに定義を置いて
ObjectData_t ObjectData[4];
FMap.hは
extern ObjectData_t ObjectData[4];
とすれば解決します。


しかし外部変数にどこからでも直接アクセスできるとメンテナンス性が低下します。
FMap.cppで
static ObjectData_t ObjectData[4];
と宣言して可視範囲をソースファイル内に限定し、アクセス用の関数を用意するとより良くなります。
外部変数にはすべてstaticを付けるようにしましょう。
他のソースファイルからアクセスされない関数にもstaticを付けましょう。

Chalaza

Re: どこかで既に定義されている

#4

投稿記事 by Chalaza » 14年前

解決しました。ありがとうございます。
引数でのやりとりばっかり考えてました。externを使ってしまえばよかったのですね。

閉鎖

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