L&M個別オンライン教室~論理と数学とプログラミングのオンライン授業~L&M個別オンライン教室~論理と数学とプログラミングのオンライン授業~L&M個別オンライン教室~論理と数学とプログラミングのオンライン授業~

C++、ヘッダーの重複(二重)読み込み防止

ヘッダーファイルの重複(二重)読み込みを防止するには、「#include guard(macro guard)と呼ばれる方法」か、「#pragma onceを用いる方法」があります。

ヘッダーファイルの重複読み込み

ヘッダーファイルを重複読み込みしてしまう問題とは、C++ソースファイルをコンパイルする際、ヘッダーファイルAとヘッダーファイルBの二つのファイルを読み込む場合に、先に読み込んだヘッダーファイルAを次に読み込むヘッダーファイルB内で再び読み込んでいると、ヘッダーファイルAの内容が二重定義されてコンパイルエラーになるという問題です。
通常、ヘッダーファイル内で他のヘッダーファイルを読み込むことはよくあるので、ヘッダーファイルの二重読み込みは容易に起こります。それを防ぐために「一度読み込んだヘッダーファイルは二度は読み込まない」という機構を作る必要があります。

二つの解決方法

防止方法は二つあります。「#include guard(macro guard)と呼ばれる方法」と、「#pragma onceを用いる方法」です。
「#include guard(macro guard)」はどのコンパイラでも利用できますが、名前の衝突が生じます。また、コンパイル速度が遅くなるコンパイラもあるそうです。
「#pragma once」は、非標準の方法で、すべてのコンパイラで採用されているわけではありませんが、現在は主なコンパイラで採用されています。こちらは名前の衝突は生じません。

#include guard(macro guard)

#include guardは、読み込まれるヘッダーファイルで「#define ヘッダーファイル名」を定義して、ヘッダーファイル名が定義済みか、定義済みでないかを確認することで、ヘッダーファイルがすでに読み込まれているかを確かめる方法です。つまり、ヘッダーファイル名が定義されていない場合のみ、そのヘッダーファイルが読み込まれていないので、ヘッダーファイルの内容を読み込みます。
具体的には、

#ifndef FILENAME
#define FILENAME
〜ファイルの内容〜
#endif

と書きます。

名前の衝突とは、二つのヘッダーファイルに同じヘッダーファイル名(FILENAME)を付けてしまい、どちらか一方のヘッダーファイルを読み込むと他方のヘッダーファイルを読み込めなくなるという問題です。
問題回避のためには統一した記法を用いることが大切になりますが、異なる制作者間のライブラリを使う場合には問題が生じます。
より詳しくは、ページ末尾の参考サイトをご覧ください。

#pragma once

#pragma onceデイレクテイブは、読み込まれるヘッダーファイルに、
#pragma once
と記述するだけで、そのヘッダーファイルの二重読み込みを防止してくれます。従って、名前の衝突も生じません。
gccはバージョン3.4からサポートしているらしく、私の使っているコンパイラgcc バージョン 4.8.2では、確かに使うことができました。
#pragma onceが使えるコンパイラ一覧は、以下の参考サイトをご覧ください。

参考サイト

Include guard, Wikipedia
http://en.wikipedia.org/wiki/Pragma_once, Wikipedia

最終修正日:2016/10/6