LoginSignup
21
17

More than 5 years have passed since last update.

stdafx.hについて調べたことメモ

Last updated at Posted at 2019-02-23

前書き

次のことが起こった。

  1. windows用アプリケーションフレームワークのMFCを使い、ヘッダファイル(.h)にクラスの定義を書き、コンストラクタを別ファイル(.cpp)に分割しようとしていた。
  2. しかし、ヘッダファイル中にあったときは動作していたプログラムが、分割したところコンパイルが通らなくなった。
  3. 原因は分割した.cppの中で、stdafx.hの上の行でクラス定義のヘッダファイルをインクルードしていたこと

そこでstdafx.hについて調べたことをメモする。
結論は、stdafx.hのインクルードはファイルの先頭でなければならない

上記の問題はC++(MFC)で自作クラスをクラス定義(.h)と関数実装(.cpp)に分割したいで質問し、回答をいただいて解決した。
プリコンパイル済みヘッダについて教えてくださったChironian様、ご回答頂いた皆様、改めましてありがとうございました。

プリコンパイル済みヘッダファイル

stdafx.hおよびstdafx.cppは、プロジェクト名.pchで生成されるプリコンパイル済みヘッダファイルstdafx.objで生成されるプリコンパイル済みタイプファイルをビルドするためのファイル。
プロジェクト名.pchたちはDebugフォルダ内等に生成される。

stdafx.h

頻繁に使われるが、変更は頻繁でないインクルードファイルのためのインクルードファイル。
このファイルの中で_AFX_NO_XXXというマクロを定義してはいけない。(ファイルを覗くと最初からそんな定義がいくつか見える。)

stdafx.cpp

#include "stdafx.h"が書いてある。
プリコンパイル済みタイプのインクルードファイルを追加する。(このファイルに必要なヘッダを追加するように読めるが、他のソースではstdafx.hに追加すると読める文も出てくる。どっち?)
プリコンパイル済みファイルというのは、プリコンパイル済みファイルを必要とするファイルのコンパイル速度を速めるためにある。最初にプロジェクトをビルドしたら、(プリコンパイル済みファイルが生成され、)その後は最初よりもっと高速にビルドできる。

ソース:
Precompiled Header Files

手動設定と注意

  • stdafx.h は、すべての .c と .cpp ファイルでインクルードされるべき
  • Visual Studioで新規プロジェクトを作成する場合stdafx.hstdafx.cppが自動で作成され、コンパイルに必要なすべてのオプションは定義されている。
  • 手動設定は、プロジェクトのプロパティから次の画像のように設定し、下記1~3を実行して有効にできる

  1. stdafx.h ファイルを作成し、プロジェクトに追加します。事前に前処理したいヘッダーをこのファイルにインクルードします。
  2. stdafx.cpp ファイルを作成し、プロジェクトに追加します。このファイルは次の 1 行のみを含みます: #include “stdafx.h”。
  3. [すべてのオプション] で stdafx.h 向けに設定を変更: [プリコンパイル済みヘッダー] オプションに “作成 (/Yc)” を設定します。

各ファイルに #include “stdafx.h” を追加する必要があります

そして、

“stdafx.h” ヘッダーは、各 *.c や *.cpp ファイルにインクルードする最初のファイルでなければいけません。

なぜ最初にインクルードするのか

例1

例として次のように解説されていた。

  1. "stdafx.h"より前のにインクルードされたファイルに#define bool charがあるとする。
  2. 全てのboolcharに置き換えられる
  3. プリコンパイル済みヘッダが想定して準備していた「めったに変更されないが頻繁に使用される処理」もbool-->charの変更を受ける
  4. プリコンパイル済みヘッダー全体の構成が壊れる

このようなことを防ぐ理由がある。他にも理由があるらしい。

例2

次のようなコードがあるとする
(#include "stdafx.h"が先頭ではない!)

int A = 10;
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[]) {
  return A;
}

これはエラーになる

error C2065: 'A' : 宣言されていない識別子

なぜなら、

これは、#include “stdafx.h” (この行を含む) 以前のすべてのテキストが、プリコンパイル済みヘッダーであると考えられます。このファイルをコンパイルすると、コンパイラーは #include “stdafx.h” 以前のテキストを .pch ファイルで置き換えようとします。その結果、”int A = 10;” の行は失われます。

正しくは

#include "stdafx.h"
int A = 10;
int _tmain(int argc, _TCHAR* argv[]) {
  return A;
}

ソース:
StdAfx.h に関する考察

なおプリコンパイル済みヘッダに関する問題には、プロジェクト全体を再コンパイル(リビルド)すると解決するものもあるらしい。

21
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
17