2
class MyClassPrivate
{
//My members.
};    

//and then
class MyClass {
private:
 MyClassPrivate* const d;
};

この「パターン」を使用する理由は何ですか?どのように正しく呼ばれていますか?

4

3 に答える 3

4

これは「実装へのポインタ」または「pimpl」と呼ばれます。http://en.wikibooks.org/wiki/C++_Programming/Idioms#Pointer_To_Implementation_.28pImpl.29を参照してください

このパターンを使用する場合、実装クラスを前方宣言し、本体を他の場所で宣言します。つまり、次のようになります。

// header
class MyClassPrivate;
class MyClass {
public:
  MyClass();
  ~MyClass();
private:
  MyClassPrivate* const d;
};

// cpp
class MyClassPrivate {
};
MyClass::MyClass() : d(new MyClassPrivate) {}
MyClass::~MyClass() { delete d; }

これを行うことの利点は、の実装がのMyClass他のユーザーに公開されないことですMyClass。実装が変更された場合、の他のユーザーをMyClass再コンパイルする必要はありません。メンバー用にインクルードする必要のあるヘッダーファイルも公開する必要がないため、コンパイル時間が短縮されます。

于 2013-01-15T11:08:07.497 に答える
3

最もよく使われるのはPimlpイディオムです。

Pimplイディオムは、ヘッダーファイルを変更されないようにする方法を説明しています。「パブリックインターフェイスの変更は避けてください」などのアドバイスをよく耳にします。したがって、プライベートインターフェイスを変更できますが、ヘッダーファイルでプライベートメソッドを定義するときに再コンパイルを回避するにはどうすればよいですか。これがPimplの機能です–プライベートインターフェイスが変更された場合のコンパイルの損傷を減らします[ 3 ]。

ここから:

利点:

  1. クラスのプライベートメンバー変数を変更する場合、それに依存するクラスを再コンパイルする必要がないため、時間が短縮され、FragileBinaryInterfaceProblemが削減されます。
  2. ヘッダーファイルは、プライベートメンバー変数で「値によって」使用されるクラスを#includeする必要がないため、コンパイル時間が高速になります。
  3. これは、SmallTalkがクラスを自動的に処理する方法のようなものです...より純粋なカプセル化。

欠点:

  1. 実装者のためのより多くの作業。
  2. サブクラスによるアクセスが必要な「保護された」メンバーでは機能しません。
  3. 一部の情報がヘッダーファイルに含まれていないため、コードを読むのがやや難しくなります。
  4. 特に関数呼び出しが仮想である場合(間接分岐の分岐予測は一般的に不十分です)、ポインターの間接参照により、実行時のパフォーマンスがわずかに低下します。

どうやってするの:

  1. すべてのプライベートメンバー変数を構造体に入れます。
  2. 構造体定義を.cppファイルに入れます。
  3. ヘッダーファイルには、構造体のForwardDeclarationのみを配置します。
  4. クラス定義で、構造体への(スマート)ポインターを唯一のプライベートメンバー変数として宣言します。
  5. クラスのコンストラクターは、構造体を作成する必要があります。
  6. クラスのデストラクタは、構造体を破棄する必要があります(おそらく、スマートポインタの使用が原因で暗黙的に)。
  7. 代入演算子とCopyConstructorは、構造体を適切にコピーする必要があります。そうしないと、無効になります。
于 2013-01-15T11:10:26.960 に答える
1

インターフェイスを実装から分離する場合は、これをPIMPLイディオムに使用できます。

多くのデザインパターンは、ストラテジーパターンなどのプライベート属性への「ポインター」も使用します。このパターンにより、実行時に別のアルゴリズムを選択できます。

また、データの操作を同じインターフェイスに準拠させる場合は、データをプライベートクラスにカプセル化し、このクラスを階層の一部にし、実行時(またはコンパイル時)に異なるデータ実装を切り替えることができます。 :))。

この良い例は、ポリゴンのデータを保持する幾何学的クラスです。各ポリゴンはポイントへのアクセスを提供します。ポリゴンエッジを削除したり、その他のさまざまなトポロジ操作を実行したりすることもできます。deletePoint、addPoint、swapEdgeなどのメソッドを使用してPolygonクラスの抽象基本クラスを提供すると、さまざまなPolygon実装をテストできます。

ポリゴンをポイントタイプのリストとして直接定義し、ポイントをさまざまなコンテナ(リストまたはベクトル)に保存することができます。Polygonクラスは、間接アドレス指定を介して定義できます。この場合、ポリゴンは実際にはポイントのリストに対するIDのリストです(一般的な意味でのリストについて話します)。このようにして、PolygonGeometryクラスのさまざまなアルゴリズムをテストし、それらがさまざまなPolygon実装でどのように機能するかを確認できます。

この背後には設計原則があります。継承よりも構成を優先します。Compositionを使用していて、実行時に決定される型に依存している場合は常に、プライベート属性ポインターがあります。

于 2013-01-15T11:08:38.423 に答える