15

すべてをヘッダーファイルだけに保持することが不可能なような依存関係のパターンはありますか?ヘッダーごとに1つのクラスのルールのみを適用した場合はどうなりますか?

この質問の目的のために、静的なものを無視しましょう:)

4

4 に答える 4

7

すでに述べた静的なものを除いて、標準のC ++には機能がないことを認識しています。これには、(ヘッダーだけでなく)完全な変換単位を定義するためのライブラリが必要です。ただし、これを行うことはお勧めしません。そうすると、ライブラリが変更されるたびに、すべてのクライアントにコードベース全体を再コンパイルするように強制するためです。ソースファイル、静的ライブラリ、または動的ライブラリ形式の配布を使用している場合は、全員に再コンパイルを強制することなく、ライブラリを変更/更新/変更できます。

于 2010-09-20T17:28:49.593 に答える
5

多くの言語機能を使用しないという明白な条件で、可能です。お気づきのとおり、staticキーワードをいくつか使用します。

いくつかのトリックが必要になる場合がありますが、確認することができます。

  1. 2つのファイルが実際にはヘッダーファイルであっても、依存関係のサイクルを断ち切る必要がある場合は常に、ヘッダーとソースの区別を維持する必要があります。
  2. フリー関数(非テンプレート)はインラインで宣言する必要があります。コンパイラーはインラインで宣言しない場合がありますが、クライアントがライブラリ/実行可能ファイルをビルドするときに再定義されたと文句を言わないように宣言されている場合。
  3. グローバルに共有されるデータ(グローバル変数とクラス静的属性)は、関数/クラスメソッドのローカル静的属性を使用してエミュレートする必要があります。実際には、呼び出し元に関する限り、それはほとんど重要ではありません(追加するだけです())。C ++ 0xでは、これが推奨される方法になることに注意してください。これは、初期化順序の大失敗から保護しながらスレッドセーフであることが保証されているためです。それまでは、スレッドセーフではありません;)

これらの3つのポイントを尊重すると、本格的なヘッダーのみのライブラリを作成できると思います(私が見逃したものを誰かが見たことがありますか?)

多くのBoostライブラリは、コードが完全にテンプレートではなかったとしても、同様のトリックを使用してヘッダーのみになっています。たとえば、Asio非常に意識的に行い、フラグを使用した代替案を提案します(Asio 1.4.6のリリースノートを参照)。

  • いくつかの機能だけが必要なクライアントは、構築/リンクについて心配する必要はありません。必要なものを取得するだけです。
  • これにもう少し依存している、またはコンパイル時間を短縮したいクライアントには、独自のAsioライブラリ(独自のフラグセットを使用)を構築し、「軽量」ヘッダーを含める機能が提供されます。

このように(ライブラリ開発者の側でもう少し努力することを犠牲にして)、クライアントはケーキを手に入れてそれも食べます。それは私が思うにかなり素晴らしい解決策です。

注:関数をインライン化できるかどうか疑問に思っstaticています。匿名の名前空間を自分で使用することを好むので、実際に調べたことはありません...

于 2010-09-20T19:24:54.067 に答える
2

ヘッダールールごとに1つのクラスは無意味です。これが機能しない場合:

#include <header1>
#include <header2>

次に、これのいくつかのバリエーションは次のようになります。

#include <header1a>
#include <header2>
#include <header1b>

これにより、ヘッダーごとに1クラス未満になる可能性がありますが、いつでも(void *)とキャストおよびインライン関数を使用できます(この場合、「インライン」はコンパイラーによって適切に無視される可能性があります)。したがって、質問は、私には、次のように減らすことができます。

class A
{
// ...
void *pimpl;
}

プライベート実装pimplがAの宣言に依存している可能性はありますか?その場合、pimpl.cpp(ヘッダーとして)はAhの前後の両方である必要がありますが、いつでも(void *)を使用して、先行するヘッダーで関数をキャストおよびインライン化できるため、これを実行できます。

もちろん、私は間違っている可能性があります。どちらの場合でも:Ick。

于 2010-09-20T17:59:41.507 に答える
1

私の長いキャリアの中で、ヘッダーのみの実装を許可しない依存関係パターンに出くわしたことはありません。

クラス間に循環依存関係がある場合は、抽象インターフェース(具体的な実装パラダイム)に頼るか、テンプレートを使用する必要があることに注意してください(テンプレートを使用すると、後でインスタンス化中に解決されるテンプレートパラメーターのプロパティ/メソッドを前方参照できます)。

これは、常にヘッダーのみのライブラリを目指すべきであるという意味ではありません。そのままで、テンプレートとインラインコードに予約する必要があります。それらは実質的な複雑な計算を含むべきではありません。

于 2014-09-08T19:34:51.387 に答える