11

単体テストを作成する必要があるレガシー コードがたくさんあります。どこでもプリコンパイル済みヘッダーを使用するため、ほとんどすべての .cpp ファイルが stdafx.h に依存しているため、テストを作成するために依存関係を解消することが難しくなっています。

私の最初の本能は、ほとんどの場合 #include ディレクティブを含むこれらの stdafx.h ファイルをすべて削除し、必要に応じてそれらの #includes をソース ファイルに直接配置することです。

これは、プリコンパイル済みヘッダーが停止する場所を決定するために stdafx.h のようなファイルを持つことに依存しているため、プリコンパイル済みヘッダーをオフにする必要があります。

stdafx.h 依存関係なしでプリコンパイル済みヘッダーを保持する方法はありますか? この問題にアプローチするより良い方法はありますか?

4

9 に答える 9

9

はい、もっと良い方法があります。

問題、IMHO、プリコンパイル済みヘッダーの「ウィザードスタイル」の問題は、不要な結合を促進し、コードの再利用を本来よりも難しくすることです。また、「stdafx.h にすべてを貼り付ける」スタイルで記述されたコードは、ヘッダー ファイルの何かを変更するとコードベース全体が毎回再コンパイルされる可能性が高いため、維持するのが面倒になる傾向があります。これにより、各変更と再コンパイルのサイクルが本来よりもはるかに長くかかるため、単純なリファクタリングに永遠にかかる可能性があります。

より良い方法は、やはり私見ですが、#pragma hdrstop と /Yc と /Yu を使用することです。これにより、プリコンパイル済みヘッダーを使用するビルド構成と、プリコンパイル済みヘッダーを使用しないビルド構成を簡単にセットアップできます。プリコンパイル済みヘッダーを使用するファイルは、ソース ファイル内のプリコンパイル済みヘッダー自体に直接依存していないため、プリコンパイル済みヘッダーの有無にかかわらずビルドできます。プロジェクト ファイルは、どのソース ファイルがプリコンパイル済みヘッダーをビルドするかを決定し、各ソース ファイルの #pragma hdrstop 行は、どのインクルードがプリコンパイル済みヘッダー (使用されている場合) から取得され、どれがソース ファイルから直接取得されるかを決定します... これは、メンテナンスを行うには、そうでない構成を使用します プリコンパイル済みヘッダーを使用しないと、ヘッダー ファイルの変更後に再構築する必要があるコードのみが再構築されます。完全なビルドを行う場合、コンパイル済みのヘッダー構成を使用してコンパイル プロセスを高速化できます。プリコンパイルされていないヘッダー ビルド オプションを使用することのもう 1 つの利点は、cpp ファイルに必要なものだけが含まれ、必要なものがすべて含まれていることを確認できることです (プリコンパイル済みヘッダーの「ウィザード スタイル」を使用する場合は難しいことです)。

これがどのように機能するかについては、http: //www.lenholgate.com/blog/2004/07/fi-stlport-precompiled-headers-warning-level-4-and-pragma-hdrstop.html ( /FI に関するものは無視してください)。#pragma hdrstop と /Yc /Yu メソッドを使用してビルドするサンプル プロジェクトがいくつかあります: http://www.lenholgate.com/blog/2008/04/practical-testing-16- --fixing-a-timeout-bug.html .

もちろん、「ウィザード スタイル」のプリコンパイル済みヘッダーの使用法から、より制御されたスタイルに移行することは、多くの場合、自明ではありません...

于 2008-11-15T23:21:40.663 に答える
4

通常、プリコンパイル済みヘッダーを使用する場合、「stdafx.h」は 2 つの目的を果たします。これは、安定した共通のインクルード ファイルのセットを定義します。また、各 .cpp ファイルでは、プリコンパイル済みヘッダーが終了する場所としてマーカーとして機能します。

あなたがやりたいことは次のように聞こえます:

  • プリコンパイル済みヘッダーをオンのままにします。
  • 各 .cpp ファイルに「stdafx.h」インクルードを残します。
  • 「stdafx.h」からインクルードを空にします。
  • 各 .cpp ファイルについて、古い「stdafx.h」からどのインクルードが必要だったかを調べます。これらを各 .cpp ファイルの #include "stdafx.h" の前に追加します。

これで、依存関係の最小限のセットが得られ、プリコンパイル済みヘッダーを引き続き使用できます。損失は​​、ヘッダーの共通セットを一度だけプリコンパイルしていないことです。これは、完全な再構築にとって大きなヒットとなります。一度に数個のファイルのみを再コンパイルする開発モードでは、それほどヒットしません。

于 2008-11-14T14:07:46.367 に答える
2

いいえ、おそらくこれ以上の方法はありませ

ただし、特定の個々の .cpp ファイルについては、プリコンパイル済みヘッダーが必要ないと判断する場合があります。その 1 つの .cpp ファイルの設定を変更して、stdafx.h 行を削除することができます。

(ただし、実際には、プリコンパイル済みヘッダー スキームがユニット テストの作成にどのように干渉しているかはわかりません)。

于 2008-11-14T13:18:19.447 に答える
2

いいえ。プリコンパイル済みヘッダーは、この方法でコンパイルされたすべてのソースに含まれる単一のヘッダーに依存しています。単一のソース (またはすべて) に対して、プリコンパイル済みヘッダーをまったく使用しないように指定できますが、それは望ましくありません。

これまで、Borland C++ コンパイラは、特定のヘッダーなしで事前コンパイルを行っていました。ただし、2 つのソース ファイルに同じヘッダーが含まれていても順序が異なる場合、実際には C++ のヘッダー ファイルの順序が問題になる可能性があるため、それらは別々にコンパイルされました...

したがって、ソースを同じ順序で厳密にインクルードした場合、または単一のインクルード ファイルを他のすべてのファイルに (最初に) インクルードした場合にのみ、ボーランドのプリコンパイル済みヘッダーが時間を節約したことを意味します... - おなじみのように聞こえますか?!?!

于 2008-11-14T13:18:55.593 に答える
2

はい。「stdafx.h/stdafx.pch」という名前は単なる慣例です。各 .cpp に独自のプリコンパイル済みヘッダーを指定できます。これはおそらく、.vcproj 内の XML を編集する小さなスクリプトで実現するのが最も簡単でしょう。欠点: プリコンパイル済みヘッダーのスタックが大量になり、それらは TU 間で共有されません。

可能ですが、賢いですか?はっきりとは言えません。

于 2008-11-14T14:43:47.090 に答える
1

私のアドバイスは、ビルドを非常に遅くしたくない限り、プリコンパイル済みヘッダーを削除しないことです。ここには基本的に 3 つのオプションがあります。

  1. プリコンパイル済みヘッダーを取り除く (非推奨)
  2. レガシ コード用に別のライブラリを作成します。そうすれば、個別にビルドできます。
  3. 1 つのプロジェクト内で複数のプリコンパイル済みヘッダーを使用します。ソリューション エクスプローラーで個々の C++ ファイルを選択し、使用するプリコンパイル済みヘッダーを指定できます。また、プリコンパイル済みヘッダーを生成するには、OtherStdAfx.h/cpp をセットアップする必要があります。
于 2008-11-14T13:19:18.010 に答える
1

プリコンパイル済みヘッダーは、すべてが同じセットのものを含むという考えに基づいています。プリコンパイル済みヘッダーを利用したい場合は、これが意味する依存関係を受け入れる必要があります。依存関係とビルド速度のトレードオフになります。プリコンパイル済みヘッダーをオフにして妥当な時間内にビルドできる場合は、必ずそれを実行してください。

考慮すべきもう 1 つの点は、ライブラリごとに 1 つの pch を持つことができるということです。したがって、コードを小さなライブラリに分割し、それぞれのライブラリの依存関係をより緊密にすることができます。

于 2008-11-14T14:53:37.743 に答える
0

afx___ のものを含める必要があるコードには、コンパイル済みのヘッダーのみを使用します。通常は UI のみであり、単体テストは行いません。UI コードは UI を処理し、単体テストを持つ関数を呼び出します (ただし、アプリがレガシーであるため、ほとんどの場合は現在ありません)。

コードの大部分では、プリコンパイル済みヘッダーを使用していません。

G.

于 2008-11-14T13:20:19.413 に答える