スライド 1

2.4
ファイル分割
大規模ソフトウェアへの第一歩
ファイル分割とは
プログラムを複数のファイルに分けること
►今までは単独のファイルに書いてきたよね
単独のファイルに書いていると
►規模が大きくなるにつれて収拾がつかなくなる
►バグを探すのも大変
►機能を追加するのも大変
►何をするにも大変
そこで必要になるのがファイル分割
2.4 ファイル分割
2
最初に言っておくこと
正直言って今回は複雑
►順序立てて説明するのが困難
恐らく一発で理解!とはいかない
►だけど、基本中の基本というレベルで必要
►是非、自分でたくさんチャレンジしてみて欲しい
順序立てた説明が困難なので・・・
►必要な知識の断片を最後に合体して理解しよう
2.4 ファイル分割
3
必要な知識
定義と宣言
(extern宣言、プロトタイプ宣言)
スコープ
#include
2.4 ファイル分割
4
よく言い間違える
定義と宣言
2.4 ファイル分割
5
定義と宣言の違い
定義:そのものを完全に表した記述
►関数なら返り値の型、名前、引数、内部動作
►変数なら型、名前
2度以上同じ定義を書くとエラーになる
宣言:識別に必要な情報だけの記述
►関数なら返り値の型、名前、引数
►変数なら型、名前
何度同じ宣言を書いてもエラーにならない
2.4 ファイル分割
6
宣言と定義まとめ
宣言
変数
定義
extern int variable;
int variable;
これはextern宣言
関数
double function(int arg);
これはプロトタイプ宣言
複数回
大丈夫
double function(int arg) {
//
// 内容ごにょごにょ
//
}
エラー
2.4 ファイル分割
7
見えるか見えないか
スコープ
2.4 ファイル分割
8
スコープとは
変数や関数の見える範囲のこと
►スコープ内からは呼び出したり代入したりできる
►スコープ内に成りうる場所では名前を重複できない
2.4 ファイル分割
9
関数のスコープ(1)
ここにプロトタイプ宣言を書いたら
スコープ内に成りうる
スコープ内に
成りうる場所
⇓
名前を重複
できない場所
スコープ
// 他のコード
// 他のコード
b.cpp
void func() {
//
// 関数の内容
//
}
// 他のコード
// 他のコード
// 他のコード
a.cpp
2.4 ファイル分割
void func();
c.cpp
10
関数の外側にある変数のスコープ
ここにextern宣言を書いたら
スコープ内に成りうる
スコープ内に
成りうる場所
⇓
名前を重複
できない場所
スコープ
// 他のコード
// 他のコード
b.cpp
int variable;
// 他のコード
// 他のコード
extern int variable;
a.cpp
// 他のコード
c.cpp
2.4 ファイル分割
11
関数の内側にある変数のスコープ
// 他のコード
スコープ内に
成りうる場所
⇓
名前を重複
できない場所
void function() {
// 他のコード
int variable;
こういうのを
ローカル変数と呼ぶ
// 他のコード
}
スコープ
// 他のコード
a.cpp
2.4 ファイル分割
12
おなじみのアイツ
#include
2.4 ファイル分割
13
実は既にファイル分割してた
C言語講習でお馴染の #include <stdio.h>
►これで stdio.h というファイルを読み込んでいる
►つまり stdio.h は分割されたファイルということ
もし #include <stdio.h> が無かったら
►printf や scanf が使えない
►つまりこれらの関数が stdio.h に含まれている
つまり stdio.h を真似すれば・・・
►ファイルを分割することが出来る!
2.4 ファイル分割
14
stdio.h の正体
内容は大量の宣言の羅列
►その中に printf や scanf もあるってこと
►関数の定義は書いていないことに注意
こういうファイルをヘッダーファイルと呼ぶ
2.4 ファイル分割
15
プログラムを構成するファイル
cpp
h
ソースファイル
ヘッダーファイル
include する側
定義だけを書く
拡張子は「.cpp」
include される側
宣言だけを書く
拡張子は「.h」
2.4 ファイル分割
16
ソースファイル
今までどおりプログラムを書く
►他のファイルと共有したいモノの命名に注意
(共有した時に名前がカブらないように!)
必要なヘッダーファイルをインクルードする
►#include <なんたら.h>
►#include "かんたら.h"
→ 元からあるやつ
→ 追加したやつ
"DxLib.h" は元からあるやつじゃないのか?
►DXライブラリはダウンロードしてきたよね
►元からというのは本当に最初からってこと
2.4 ファイル分割
17
ヘッダーファイル
ソースファイルとセットで作る
►「keyboard.cpp」と「keyboard.h」という感じ
共有したいモノの宣言を書く
►つまり他のファイルに公開したい関数や変数のこと
宣言については7ページを見よう
2.4 ファイル分割
18
たったこれだけ
ファイル分割そのものはこれだけのこと
►でも言われただけじゃ難しいよね
►そういうわけで実例を見てみよう
2.4 ファイル分割
19
どんだけ説明しても難しいもんは難しいので
実例を見てみよう
2.4 ファイル分割
20
ゲームを作ってたら
break;
case GAME:
// ゲーム処理
// もちろん長い
#define TITLE
(0)
#define GAME
(1)
#define GAMEOVER (2)
break;
int WINAPI WinMain(略) {
case GAMEOVER:
// 初期化が何行か
// ゲームオーバー処理
int mode = TITLE; 長くて読みにくい!// 短いはずがない
while (1) {
break;
// 定型文がいくらか
}
// 定型文がいくらか
switch (mode) {
case TITLE:
// タイトル処理
// めっちゃ長い
break;
case GAME:
・・・
}
DxLib_End();
return 0;
}
2.4 ファイル分割
21
まずは関数化しよう
・・・
#define GAMEOVER (2)
void TitleProcess() {
// 長い処理
}
void GameProcess() {
// 長い処理
}
関数化してスッキリした
・・・
int WINAPI WinMain(略) {
// 初期化が何行か
int mode = TITLE;
・・・
・・・
while (1) {
// 定型文がいくらか
switch (mode) {
case TITLE:
TitleProcess();
break;
case GAME:
GameProcess();
break;
case GAMEOVER:
GameOverProcess();
break;
}
// 定型文がいくらか
}
・・・
2.4 ファイル分割
22
それでも効果は薄い
結局長いことには変わりない
►場所が変わった
►折りたためるようになった(Visual C++の機能)
変数の扱いが難しくなった
►関数の実行1回は1フレームに相当する
(今までは関数1回がゲーム全体に相当した)
►ゲーム全体を通して保存しておく変数はどうする?
2.4 ファイル分割
23
ファイル分割の方針
int
mode
void
GameProcess
int
WinMain
game.cpp
main.cpp
void
TitleProcess
title.cpp
変数
関数
呼び出し
2.4 ファイル分割
void
GameOverProcess
gameover.cpp
24
ファイル分割の方針
int
mode
void
GameProcess
int
WinMain
game.cpp
main.cpp
void
TitleProcess
title.cpp
変数
関数
変更
2.4 ファイル分割
void
GameOverProcess
gameover.cpp
25
ポイントは「共有」
方針によって共有したいモノが明らかになった
int
mode
つまりコイツらの宣言を
ヘッダーファイルに書く
void
GameProcess
void
TitleProcess
void
GameOverProcess
2.4 ファイル分割
26
ヘッダーファイルを作ろう
ヘッダーファイルに書くことはこれだけ
►「これを共有しますよー」という情報
►驚くほど短いけど本当にこれだけ
►なぜなら宣言だから
extern 宣言
プロトタイプ宣言
extern int mode;
7ページ
でやった
void TitleProcess();
main.h
title.h
void GameProcess();
game.h
void GameOverProcess();
gameover.h
2.4 ファイル分割
27
ソースファイルを作ろう
ソースファイルは・・・
►先頭で必要なヘッダーファイルをインクルードする
►あとは本当に今まで通り
#include "title.h"
#include "game.h"
#include "gameover.h"
#include "main.h"
int mode;
int WINAPI WinMain(略) {
・
・
・
void TitleProcess() {
//
// タイトル処理
//
}
他のモードも同様
title.cpp
main.cpp
2.4 ファイル分割
28
補足事項
staticキーワードについて
►Wikiを見てね
http://nanzanmmc.net/pc/lecture/game/add
2.4 ファイル分割
29