4

静的ライブラリを作成していると考えてください。クラスを持たせましょうFoo

// mylib.h
#include <dependency_header_from_other_static_library.h>

class Foo {
    // ...
private:
    type_from_dependent_library x;
}

ご覧のとおり、このライブラリ(これを呼びましょうmylib)は別のライブラリに依存しています。それはうまくコンパイルされます。しかし、ユーザーがそのコード(を使用Fooして含むmylib.h)をコンパイルし、私のライブラリとリンクすると、コンパイルは失敗します。これは、ユーザーがdependency_header_from_other_static_library.hコードをコンパイルするためにもヘッダーファイルを持っている必要があるためです。

この依存関係をユーザーから隠したい。これはどのように行うことができますか?頭に浮かぶのはPIMPLイディオムです。好き:

// mylib.h
#include <dependency_header_from_other_static_library.h>

class Foo {
    // ...
private:
    class FooImpl;
    boost::shared_ptr<FooImpl> impl_;
}

// mylib_priv.h
class FooImpl {
    // ...
private:
    type_from_dependent_library x;
}

Fooただし、のクラスのインターフェイスを複製する必要がありますFooImplPIMPLそして、私の場合に使用するのはやり過ぎですか?

ありがとう。

4

1 に答える 1

8

ヘッダーを他のヘッダーから切り離す場合、使用できる可能性のあるいくつかのアプローチがあります。

  1. 使用されているライブラリがその型を宣言する方法について約束している場合は、ヘッダーで必要な型を前方宣言できる可能性があります。もちろん、これは、これらのタイプをポインターまたはヘッダーの関数シグネチャーとしてのみ参照できることを意味しますが、これで十分な場合があります。たとえば、使用されているライブラリclass LibraryTypeに使用する必要のあるライブラリがあると約束されている場合は、次のようにすることができます。

    // Foo.h
    class LibraryType;
    class Foo {
        // ...
        LibraryType* data;
    };
    

    これにより、ヘッダーを含めずに、またPImplアプローチをジャンプせずに、タイプを使用するために必要なたるみを減らすことができます。

  2. ライブラリがタイプを宣言する方法について約束していない場合はvoid*、対応するタイプを参照するために使用できます。もちろん、これは、実装でデータにアクセスするときはいつでも、void*を適切なタイプにキャストする必要があることを意味します。タイプは静的にわかっているので、使用static_cast<LibraryType*>は完全に問題ありません。つまり、キャストによるオーバーヘッドはありませんが、それでも比較的苦痛です。

  3. もちろん、他の選択肢は、PImplイディオムを使用することです。タイプが合理的なサービスを提供する場合、それはおそらくインターフェースをかなり変更するでしょう、そしてそれはクラス自体と私的に宣言されたタイプの間のインターフェースを複製することにはあまりならないはずです。また、プライベートタイプは単なるデータコンテナであることに注意してください。つまり、プライベートタイプを単に作成するだけでstruct、アクセスを保護することはできません。唯一の実際の問題は、デストラクタが呼び出されたポイントで型の定義が表示されていることを確認する必要があることです。を使用してこれをstd::shared_ptr<T>(new T(/*...*))手配します。

事実上、3つのアプローチはすべて同じことを行いますが、手法はわずかに異なります。これらのアプローチは、実装にのみ定義が知られているヘッダーファイルで使用される不透明なハンドルを提供します。このように、ライブラリのクライアントは、対応するヘッダーファイルをインクルードする必要はありません。ただし、ライブラリの構築時にシンボルが解決されない限り、クライアントは使用されているライブラリにアクセスできる必要があります。

于 2012-10-27T23:42:16.183 に答える