ページ 11

分割コンパイルについて

Posted: 2012年9月16日(日) 18:16
by イマダニ
分割コンパイルではよく別ファイルで定義したものをまた別のファイルで呼び出すことがありますよね。
たとえばこんな感じに
void sshot(PLAY play,SHOT shot[MAX_SHOT])
プレイヤーが弾を撃つための関数やらなにやらが書かれている、
shot.cppにあるsshot関数でプレイヤーの座標を使うためplay.hで定義した構造体を呼び出したりとかありますよね。
この時、shot.hに

コード:

#ifndef DEF_SHOT_H
#define DEF_SHOT_H
#define MAX_SHOT 100
typedef struct{
	int img;
	double x,y;
	bool flag;
	int sound;
}SHOT;
void sini(SHOT shot[MAX_SHOT]);
void sshot(PLAY play,SHOT shot[MAX_SHOT]);
void sgraph(SHOT shot[MAX_SHOT]);
#endif
こう書きます。すると、

error C2065: 'PLAY' : 定義されていない識別子です。
error C2146: 構文エラー : ')' が、識別子 'play' の前に必要です。

というたくさんのエラーが出ます。
ここで私は「ああ、ヘッダファイルにもplayerの構造体が定義されてるplayer.hをインクルードしなきゃならないのか」と思い、こう書きました。

コード:

#include "player.h"
#ifndef DEF_SHOT_H
#define DEF_SHOT_H
#define MAX_SHOT 100
typedef struct{
	int img;
	double x,y;
	bool flag;
	int sound;
}SHOT;
void sini(SHOT shot[MAX_SHOT]);
void sshot(PLAY play,SHOT shot[MAX_SHOT]);
void sgraph(SHOT shot[MAX_SHOT]);
#endif
するとエラーが出ず、無事作動しました。
ですが、本当にこういう書き方でいいのでしょうか?
アドバイスお願いします。

Re: 分割コンパイルについて

Posted: 2012年9月16日(日) 20:35
by ibrn
基本的にはそれで問題ないと思います(play.hにPLAYがきちんと定義されていれば。)
ただ、#include "player.h"はインクルードガード(#ifdef DEF_SHOT_H ,#define DEF_SHOT_H)の後に書くよう
習慣づけることをオススメします。

Re: 分割コンパイルについて

Posted: 2012年9月17日(月) 00:49
by beatle
ibrnさんの仰るとおり、基本的には問題ありません。

今は問題にぶち当たっていないようですが、そういうパターンで#includeしてよく出会う問題として、
player.hの中でSHOT構造体を使っており、どっちを先に#includeするかを決められない(どっちにしてもエラーがでる)
というものがあります。
こういう時は、構造体の前方宣言を行います。

player.hを#includeせずに

コード:

struct PLAY_st;
typedef PLAY_st PLAY;
のようにすることで解決できます。

この場合、対応する.cファイルの方でplayer.hを#includeする必要があります。
しないと、不完全型(incomplete type)にアクセスしようとしている、という警告が出るでしょう。

Re: 分割コンパイルについて

Posted: 2012年9月17日(月) 16:52
by イマダニ
なるほど勉強になります。不安が解消されました。
ibrnさん、beatleさんこんな些細な質問にわざわざ答えてくださり
ありがとうございました!