質問
すべてをヘッダーファイルに保つことは不可能な依存症のパターンはありますか?ヘッダーごとに1つのクラスのルールを実施した場合はどうなりますか?
この質問の目的のために、静的なことを無視しましょう:)
解決
標準のC ++には機能がないことを知っていますが、すでに述べた統計を除いて、(ヘッダーのみではなく)完全な翻訳ユニットを定義するライブラリが必要です。ただし、それを行うことはお勧めしません。なぜなら、あなたがそうするとき、あなたはあなたのライブラリが変更されるたびにすべてのクライアントに彼らのコードベース全体を再コンパイルするように強制するからです。ソースファイルまたは静的ライブラリまたはダイナミックライブラリ形式の配布を使用している場合、ライブラリを変更/更新/変更することなく、全員に再コンパイルを強制することができます。
他のヒント
私はそれが可能だ、私は言うだろう、多くの言語機能を使用しないという明示的な条件で:あなたが気づいたように、いくつかの用途 static
キーワード。
いくつかのトリックが必要になる場合がありますが、レビューできます。
- 2つのファイルが実際にヘッダーファイルになる場合でも、依存関係サイクルを破る必要がある場合はいつでも、ヘッダー /ソースの区別を維持する必要があります。
- 自由関数(非テンプレート)はインラインで宣言する必要があります。コンパイラはインラインではない場合がありますが、クライアントがライブラリ /実行可能ファイルを構築したときに再定義されていると不平を言うことはありません。
- グローバルに共有されたデータ(グローバル変数とクラスの静的属性)は、関数 /クラスメソッドのローカル静的属性を使用してエミュレートする必要があります。実際には、発信者に関する限りはほとんど重要ではありません(ただ追加するだけです
()
)。 C ++ 0xでは、初期化順序の大失敗から保護しながらスレッドセーフであることが保証されているため、これが好まれる方法になります...それまでは...それはスレッドセーフではありません;)
これらの3つのポイントを尊重して、私はあなたが本格的なヘッダーのみのライブラリを書くことができると思います(誰も私が見逃したものを見ましたか?)
多くのブーストライブラリは、コードが完全にテンプレートではなかったとしても、同様のトリックをヘッダーのみにして使用しています。例えば Asio
非常に意識的に、フラグを使用して代替案を提案します(参照 ASIO 1.4.6のリリースノート):
- いくつかの機能を必要とするクライアントは、構築 /リンクを心配する必要はありません、彼らは自分が必要とするものをつかむだけです
- もう少し依存している、またはコンピレーション時間を削減したいクライアントは、独自のASIOライブラリを構築する機能(独自のフラグのセットを使用して)を提供し、「軽量」ヘッダーを含めることができます
このようにして(ライブラリ開発者の一部でさらに努力の価格で)クライアントはケーキを手に入れて食べます。それは私が思うにかなりいい解決策だと思います。
ノート: 私は疑問に思っています static
関数がインラインになる可能性があります。私は自分で匿名の名前空間を使用することを好むので、実際にそれを調べることはありません...
ヘッダールールごとに1つのクラスは意味がありません。これがうまくいかない場合:
#include <header1>
#include <header2>
それから、これのいくつかのバリエーションは次のとおりです。
#include <header1a>
#include <header2>
#include <header1b>
これにより、ヘッダーごとに1つのクラスが1つ未満になる可能性がありますが、常に(void*)を使用し、キャストとインライン関数を使用できます(この場合、「インライン」はコンパイラによって正当に無視される可能性があります)。ですから、私には質問があるように思えますが、次のようになります。
class A
{
// ...
void *pimpl;
}
プライベート実装であるPIMPLが宣言に依存する可能性はありますか?もしそうなら、pimpl.cpp(ヘッダーとして)は、AHの前と従う必要がありますが、いつでも、再び(void*)を使用し、ヘッダーの前のキャストとインライン関数を使用することができます。
もちろん、私は間違っている可能性があります。どちらの場合でも:ick。
私の長いキャリアでは、ヘッダーのみの実装を禁止する依存関係パターンに出くわしていません。
クラス間に循環依存関係がある場合は、抽象的なインターフェイス - 具体的な実装パラダイム、またはテンプレートを使用する必要がある場合があることに注意してください(テンプレートを使用すると、インスタンス化中に解決されるテンプレートパラメーターのプロパティ/方法を転送することができます。 )。
これは、常にヘッダーのみのライブラリを目指すべきであるという意味ではありません。彼らはそうであるように、彼らはテンプレートとインラインコードに予約されるべきです。実質的な複雑な計算を含めるべきではありません。