8

大規模な C++ プロジェクトでの問題の 1 つは、ビルド時間です。依存関係ツリーの上位に作業が必要なクラスがいくつかありますが、通常は、すべてのビルドに非常に長い時間がかかるため、作業を避けます。必ずしもパブリック インターフェイスを変更する必要はありませんが、プライベート メンバーを変更する必要がある場合があります (キャッシュ変数の追加、プライベート メソッドの抽出など)。あなたが直面している問題は、C++ ではプライベート メンバーでさえパブリック ヘッダー ファイルで宣言されているため、ビルド システムですべてを再コンパイルする必要があることです。

この状況であなたは何をしますか?

私が知っている2つの解決策をスケッチしましたが、どちらにも欠点があり、まだ考えていないより良い解決策があるかもしれません.

4

6 に答える 6

9

ニキビのパターン:

ヘッダー ファイルでは、前方宣言された実装クラスへのパブリック メソッドとプライベート ポインター (pimpl ポインターまたはデリゲート) のみを宣言します。

ソースで、実装クラスを宣言し、パブリック クラスのすべてのパブリック メソッドをデリゲートに転送し、パブリック クラスのすべてのコンストラクターで pimpl クラスのインスタンスを構築します。

プラス:

  • すべてを再コンパイルすることなく、クラスの実装を変更できます。
  • 継承はうまく機能しますが、構文だけが少し異なります。

マイナス:

  • 委譲を行うために書くばかげたメソッド本体がたくさんあります。
  • ステップスルーするデリゲートがたくさんあるので、デバッグするのはちょっと厄介です。
  • 小さなオブジェクトがたくさんある場合に問題になる可能性がある、基本クラスの余分なポインター。
于 2009-06-09T23:26:13.620 に答える
6

John Lakos の『Large Scale C++ Software Design 』は、大規模な C++ プロジェクトの構築に伴う課題に対処する優れた本です。問題と解決策はすべて現実に基づいており、確かに上記の問題は詳細に議論されています。強くお勧めします。

于 2009-06-10T00:08:34.127 に答える
2

継承の使用:

ヘッダーで、パブリック メソッドを純粋仮想メソッドおよびファクトリとして宣言します。

ソースで、インターフェイスから実装クラスを派生させて実装します。ファクトリの実装では、実装のインスタンスを返します。

プラス:

  • すべてを再コンパイルすることなく、クラスの実装を変更できます。
  • 簡単かつ確実に実装できます。

マイナス:

  • public ベースの (private) 実装のメソッドの一部を継承する必要がある public 基本クラスの (public) 派生インスタンスを定義するのは本当に厄介です。
于 2009-06-09T23:27:23.523 に答える
0

pimpl/handle-body イディオムをリファクタリングして使用し、純粋な仮想インターフェイスを使用して実装の詳細を非表示にすることが一般的な答えのようです。大規模なシステムを設計するときは、コンパイル時間と開発者の生産性を考慮する必要があります。しかし、ユニット テスト カバレッジのない既存の大規模な C++ システムで作業している場合はどうでしょうか。通常、リファクタリングは問題外です。

いくつかの一般的なヘッダー ファイルに触れた後、コンパイラに世界をコンパイルさせたくない場合に私が通常行うことは、再コンパイルが必要であることがわかっているファイルのみをコンパイルするメイクファイル/スクリプトを作成することです。たとえば、非仮想プライベート関数をクラスに追加する場合、ヘッダー ファイルが他の 100 のファイルに含まれている場合でも、クラスの cpp ファイルのみを再コンパイルする必要があります。その日の出発前に、世界を再構築するためのクリーン ビルドを開始します。

于 2009-06-10T03:01:06.790 に答える
0

別のクラス B のポインターによって参照されるクラス A の前方宣言を使用できます。その後、ヘッダー ファイルではなく、クラス B の実装ファイルにクラスの A ヘッダー ファイルを含めることができます。そうすれば、クラス A に加えた変更は、クラス B のヘッダー ファイルを含むソース ファイルには影響しません。クラス A のメンバーにアクセスするクラスは、クラス A のヘッダー ファイルをインクルードする必要があります。

于 2009-06-10T00:04:36.553 に答える
-1

なし。

1つを使用することのポイントはわかりますが、次の議論は多くのシナリオでそのポイントを軽減すると思います:

  1. 明確さが第一です。ランタイム速度の明快さを妥協することを 2 回考慮する必要がある場合、 コンパイル時間の速度の明快さを妥協することはどうですか?
  2. プライベート メンバーは頻繁に変更しないでください。
  3. 通常、すべてを再構築するのにそれほど時間はかかりません。
  4. より高速なツールが将来登場するため、コンパイル速度の問題は自動的に軽減されます。コードが自動的に明確になるわけではありません。
  5. とにかく頻繁に再構築する必要があります。
  6. Incredibuildを試しましたか?

もちろん、最終的には経済的な決定です。プロジェクトで「3」の重みが重要で、何らかの理由で「6」を適用できない場合は、先に進んでください。これらのテンプレートを使用すると、失うよりも多くを得ることができます。

于 2009-06-10T07:43:28.247 に答える