#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のトップページをご覧ください。