ショートカット
ファシリテーター × あり方
コーディングの向こう側
Hello, ANOTHER world!
オブジェクト指向のはなし
プログラミングのはなし
C言語実力診断クイズ
eSkillBooks
プログラミングのはなし

プロトタイプをインクルードする

プログラム中の誤りを自動的に検出できるように工夫することが非常に大事です。以前に述べたデバッグコードもその工夫のひとつです。今回は、リンクエラーを防ぐための手法を紹介します。まず、次のコードを見てください。

SAMPLE
CODE
ファイル名:main.cpp
#include "sub.h"

void main()
{
    Open( "filename" );
    Close();
}
ファイル名:sub.h
#ifndef INCLUDED_SUB_H
#define INCLUDED_SUB_H

void Open( const char *pcFileName );
void Close();

#endif // #ifndef INCLUDED_SUB_H
ファイル名:sub.cpp
#include <assert.h>
#define ASSERT(C) assert(C)

#include "sub.h"

static bool fs_bOpen = false;

void Open( const char *pcFileName )
{
    ASSERT( fs_bOpen == false );
    ...
    fs_bOpen = true;
}

void Close()
{
    ASSERT( fs_bOpen == true );
    fs_bOpen = false;
    ...
}

このコードは別のトピックで掲載したものですが、リンクエラーを未然に防ぐ工夫をしています。

まず sub モジュールの実装とインターフェイスを分離しています。"sub.cpp" が実装で、"sub.h" がインターフェイスですね。sub モジュールの中でほかのモジュールから利用される部分だけをインターフェイスとして抽出しています。main モジュールでは、sub モジュールの機能を利用するために "sub.h" をインクルードしています。ここまでは普通です。

"sub.cpp" からも "sub.h" をインクルードしていることに注目してください。ここがポイントです。こうやって、実装とインターフェイスが正確に同じになるようにしています。実装側で関数に引数を追加したときに、もしインターフェイス側のプロトタイプの修正を忘れてしまったらどうなるか想像してみてください。上記の工夫があればコンパイルエラーで修正のし忘れに気づくことができます。しかしこの工夫をしていなかったら、運良くリンクエラーが発生するまでは気づかないでしょう。処理系によっては、リンクエラーさえ出力されません。

この手法は、C++ で class を使っている場合にも適用できます(適用すべきです)。C++ では必ずリンクエラーが起こるのでこの手の誤りを検出できないということはないでしょうが、誤りは早期に発見できる方が良いでしょう。

(「プログラミングのはなし」は1998年1月から1999年1月にかけて作成されたコンテンツです。)