ビルド速度が大きくなり始め、生産性に影響を与えている状況に遭遇しました。前方宣言を使用する前に、ヘッダーの依存関係を最小限に抑えていました。コンパイル時間を短縮する方法として、これらの依存関係をさらに減らすために、宣言を転送することにしました。
フォワード宣言の概念は理解していますが、 this に出会うまでは、フォワード宣言がどの程度可能かはよくわかりませんでした。私が理解しているように、すべてのメソッド/関数パラメーターと関数宣言の戻り値の型を転送宣言できます。
私には多くの状況があります(ヘッダーにガードが含まれていると想定しています)。
//myclass.h
#include "someclass.h"
#include "someotherclass.h"
class MyClass{
public:
SomeOtherClass foo(SomeClass y);
};
前方宣言により、次のようなことができるようになります。
//myclass.h
class SomeClass;
class SomeOtherClass;
class MyClass{
public:
SomeOtherClass foo(SomeClass y);
};
//include actual header files in myclass.cpp
私はこれが何らかの形で呼び出しサイトにヘッダーが含まれることを必要とすると思いますが、ヘッダーからインクルードを削除します。そして、呼び出し元はその呼び出しを使用しません。呼び出しサイトでその依存関係をまったく必要とすることによる純利益となると思います。
これまでにこのパターンを見たことがないので(クラスメンバーとプライベート関数タイプでのみ)、これを行うことのマイナス面があるかどうか疑問に思っています。これらすべての型を転送宣言するだけではいけない理由はありますか?
はい、少なくとも1つの理由が存在します。
Google Style Guide は、前方宣言によりコンパイル時間を改善できることを認めていますが、開発者には#include
宣言(可能な場合は特にサードパーティのライブラリを使用する場合)と、いくつかの理由を示します。
- フォワード宣言は依存関係を隠すことができ、ユーザーコードはヘッダーが変更されたときに必要な再コンパイルをスキップできます。
- ライブラリへのその後の変更により、前方宣言が壊れる可能性があります。関数とテンプレートの前方宣言は、ヘッダーの所有者がAPIに他の互換性のある変更(パラメータータイプの拡大、デフォルト値を持つテンプレートパラメーターの追加、新しい名前空間への移行など)を行わないようにする可能性があります。
- 名前空間std ::からのシンボルの転送を宣言すると、未定義の動作が発生します。
- 前方宣言が必要か、完全な#includeが必要かを判断するのは難しい場合があります。 #includeをforward宣言で置き換えると、コードの意味が暗黙的に変更される可能性があります。
- ヘッダーから複数のシンボルを前方宣言すると、単に
#include
ingヘッダー。- 前方宣言を有効にするようにコードを構造化すると(オブジェクトメンバーの代わりにポインターメンバーを使用するなど)、コードが遅くなり、複雑になる可能性があります。
もちろん、ウェブの他の場所には 反対意見 があります。対象の最も合理的な[引用が必要な]治療は、どちらのアプローチにも利点と欠点があることを認めているため、いつものように、特定の状況でこのツールを使用するかどうかを判断する必要があります。
これらは、主題について書かれた唯一の記事ではなく、信頼できるものでもありません。偶然偶然見つけた2つの関連ページ(1つはそれらの1つ)他への応答であること);もちろん、あなたが見たければ、もっと広い議論が見つかるでしょう。
この回答は、主に他のサイトから情報をコピーすることによって作成されました。私がGoogleに組み込んだ検索用語は次のとおりです。
「c ++」「前方宣言を使用しない」
これにより、1ページ目に適切なサイトのリストが表示され、従来の知識ではこの言語機能の長所と短所が示されているかもしれないことを簡単に調べることができます。
これらやその他の用語や検索クエリ形式を試して、他の多くのオプションの言語ツールの使用についての論争を見つけることもできます。私の個人的なお気に入りは現在ジェネリックです(Go 2に含まれている場合は、Go 1が引き続きサポートされている限り引き続き使用し、別のお気に入りの言語を見つけます)。