#pragma twice

KAB-studio > プログラミング > #pragma twice > 305 Version 15.05 インクルードの順番

#pragma twice 305 Version 15.05 インクルードの順番

前のページへ 表紙・目次へ 次のページへ

 Version 15.05
インクルードの順番

「前回は、ヘッダーファイルがなぜ便利なのか説明しました」
『よーするに関数を呼ぶにはその宣言が必要、その宣言だけをまとめた
ヘッダーファイルを使い回せばいろんなソースファイルから関数が呼べる、
ってことよね』
「そういうこと。そんなヘッダーファイルについて、細かいテクニックや、
気を付けておかなければならない点について説明します」
『はーい』
「まずはこれから」

・2種類のインクルード方法について

#include <Windows.h>
#include "Sub.h"

『あ、 <> で囲むのと "" で囲むのと2種類あるんだよね』
「そう。 <> は API や MFC のヘッダーファイルをインクルードする時に、
"" はプロジェクト内のヘッダーファイルをインクルードするときに使いま
す」
『 API の?』
「そう。具体的には……メニューの【ツール】−【オプション】の
【ディレクトリ】ページで、【表示するディレクトリ】を
【インクルードファイル】を選んでみて」
『 C:\Program Files\Microsoft Visual Studio\VC98\INCLUDE とかある』
「これは、 Visual C++ をインストールした時に、 API や MFC の
ヘッダーファイルをインストールしたフォルダ。で、実は <> で
インクルードするのは、ここに書かれているフォルダの中の
ヘッダーファイルなんです」
『そっか、 API とかもちゃんとヘッダーファイルがあって、ここに置かれ
てて、 <> だとここを見に行って……』
「だから、逆もOK」
『逆?』
「たとえばここから Windows.h をプロジェクトへコピーして "Windows.h" 
でインクルードしたり」
『できるんだ……』
「プロジェクトのヘッダーファイルを置いてあるフォルダをここの設定に追
加して <Sub.h> ってインクルードしたり」
『それもできるんだ……』
「特に、自分でライブラリを作って使う場合には、ヘッダーファイルの置い
てあるフォルダをここで指定すれば」
『ライブラリっぽく使える! なんかちょっとかっこいいかも』
「では次」

・インクルードの順番

「前回、インクルードは〈コピペするようなもの〉って説明しました」
『うん、ただファイルの中身をそのまま置き換えるだけなんだよね』
「だから、インクルードする順番が実は重要なんです」
『順番?』
「プログラムのコンパイルって、上からするって説明したでしょ」
『うん。上から見ていって、関数の宣言があったら憶えておく、とか』
「だから、こういう場合に問題になります。まず Typedef.h ってファイル
を追加して」
『ほい。【ファイル】−【新規作成】で【ファイル】の
【C/C++ ヘッダーファイル】、ファイル名は Typedef.h ね』
「その中にこう書いて」

// Typedef.h
typedef int INTEGER;

『 typedef って、型の別の名前付けるのだよね』
「そう、 Version 5.08 ( No.073 ) でやったね。次に Sub.cpp をこうしま
す」

// Sub.cpp

#include "Typedef.h"
#include "Sub.h"

void Test( INTEGER p_i )
{
}
「さらにそのヘッダーファイル Sub.h をこうします」

// Sub.h

void Test( INTEGER p_i );

『 Typedef.h の INTEGER を引数に使ってるわけね』
「で、最後にこれを使う Main.cpp 」

// Main.cpp
#include <Windows.h>

#include "Typedef.h"
#include "Sub.h"

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    Test( 100 );
    return 0;
}

『ビルドっと。あれ、普通に通ったけど』
「そう、これは〈正解〉」
『じゃあ間違った例は?』
「さっきも言ったように、インクルードファイルの順番を間違えた場合」

// Main.cpp
#include <Windows.h>

#include "Sub.h"
#include "Typedef.h"

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    Test( 100 );
    return 0;
}

『あ、 Sub.h と Typedef.h のインクルードの順番が逆だ』
「そうするとこういうコンパイルエラーが出ます」

error C2065: 'INTEGER' : 定義されていない識別子です。

「これは、インクルードファイルをそのまま展開してみればわかると思いま
す」

void Test( INTEGER p_i );

typedef int INTEGER;

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    Test( 100 );
    return 0;
}

『あ、 typedef する前に Test() の引数で使ってる!!』
「そう、上から順番に見ていくから、 Test() の引数で使う前に typedef 
してなきゃいけない、だけどしてないからコンパイルエラーになるんです」
『順番が大事ってこういうことなんだ』
「これは自分で作ったヘッダーファイルだから分かりやすいけど、 API や
MFC のヘッダーファイルでもこういうことはあるから注意して」
『……ってゆーか、それってもしかしてヘッダーファイルの中身見なきゃ、
どっちを先にとかって分からなくない?』
「うん、わからないかも」
『げ』
「逆に言うと、ヘッダーファイルは見ればなんとかなるって言うことも言え
るけどね」
『それはそうだけど……』
「順番に関して、どうしようもない場合とかもあります」
『どうしようもない場合?』

・ヘッダーファイル同士の相互参照

「まず Sub.h が……」

// Sub.h

void Test( INTEGER p_i );

typedef int INTEGER2;

『もうひとつ int が再定義』
「そして Typedef.h が……」

// Typedef.h

typedef int INTEGER;

void Test2( INTEGER2 p_i );

『こっちでその INTEGER2 を使ってる……?』
「どっちを先にインクルードすればいいと思う?」
『 Typedef.h の Test2() に Sub.h の INTEGER2 があるから、 Sub.h を先
に……したら、さっきと同じことになっちゃうから、 Typedef.h を先に……
でもそしたら……これってダメじゃん!!』
「そういうこと。こういうヘッダーファイルを作ると、どちらを先に
インクルードしてもコンパイルエラーになります」
『……じゃあ、そういう場合、どうすればいいの?』
「このヘッダーファイルを自分で作った場合には、整理すればいいだけ。 
INTEGER2 を Typedef.h に、 Test2() を Sub.h に置けば問題ないでしょ」
『そっか、 typedef は Typedef.h に、関数は Sub.h に……』
「最悪、自分が作ったヘッダーファイルじゃないとしても、全部コピペして
新しいヘッダーファイルを自分で作っちゃえばいいだけ」
『へ? それっていいの?』
「もちろん。ヘッダーファイルは、単にプログラムの〈情報〉があるだけ。
だから使いづらかったら自分で作り直しちゃえばいいんです」
『それって結構すごいかも……』
「ま、最終手段だけどね」

/*
    Preview Next Story!
*/
『ヘッダーファイルを作るって、なんかすごすぎるんだけど』
「ヘッダーファイルは古い技術の集まりだからね」
『古いの?』
「古いよ、だから手作業的な部分が多いし、小さなテクニックも」
『テクニック?』
「というわけで次回」
< Version 15.06 ヘッダーファイルを2度読み込む? >
『につづく!』
「この2度読み込むのを回避する方法とかね」
『あれ? 前に教わってない?』
「ぎく」
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。