2

例えば

// Implementation.
struct PrivatePoint {
  void SomePrivateMethod();

  double x;
  double y;
}

struct Point : private PrivatePoint {
  double DistanceTo(const Point& other) const;
}

これはPimplイディオムに似ているようです。これには、私が本当に気に入っている2つの利点があります。

  1. SomePrivateMethodはテスト可能です。代わりにSomePrivateMethodがPointでプライベートとして宣言されている場合、テストから呼び出すことはできません。それをパブリックまたはPointで保護されていると宣言した場合、テストはそれを呼び出すことができますが、Pointの通常のユーザーもそうすることができます。
  2. プライベートデータへのアクセスは、Pimplイディオムで行う方法と比較して、読み取りと書き込みが簡単です。これは、ポインターを経由する必要がないためです。

Point::DistanceTo(const Point& other) {
  SomePrivateMethod();

  double dx = other.x - x;
  double dy = other.y - y;
  return sqrt(dx * dx + dy * dy);
}

対。

Point::DistanceTo(const Point& other) {
  ptr->SomePrivateMethod();

  double dx = other.ptr->x - ptr->x;
  double dy = other.ptr->y - ptr->y;
  return sqrt(dx * dx + dy * dy);
}
4

3 に答える 3

2

あなたの提案にはいくつかの欠点があります....

ユーザーは「プライベート」クラスに自分自身を結合することができます。

pimplイディオムの主な目的は、コンパイルファイアウォールとしての機能であり、実装ファイルでプライベートメンバーを指定できるため、ヘッダーに触れたり、クライアントの再コンパイルを必要としたりトリガーしたりすることなく、より高速で再リンクするだけでなく、変更することができます。動的にロードされたライブラリを更新する場合は、クライアントアプリに関連するアクションを必要としない場合もあります。あなたはこれらの利益を失います。

SomePrivateMethodはテスト可能です。代わりにSomePrivateMethodがPointでプライベートとして宣言されている場合、テストから呼び出すことはできません。それをパブリックまたはPointで保護されていると宣言した場合、テストはそれを呼び出すことができますが、Pointの通常のユーザーもそうすることができます。

他にも便利なハックのオプションがあります。たとえば、テストコードで友情を宣言したり、プリプロセッサを使用してデータを公開するテストモードでビルドしたりできます。

于 2012-09-21T02:07:04.530 に答える
1

プライベート継承は構成(およびpimpl)と非常に似ていますが、考慮すべきいくつかの欠点があります。

  1. PrivatePoint定義をパブリックヘッダーに表示する必要があります。これにより、PrivatePointへのコンパイル時の依存関係が導入され、PrivatePointが変更されるたびにPointのクライアントが再コンパイルする必要があります。pimplの場合、これは当てはまりません。次のようにPrivatePointを前方宣言するだけで十分です。structPrivatePoint;

  2. カプセル化はウィーカーです。プライベート継承を使用すると、Pointを拡張するクライアントは、独自のバージョンのSomePrivateMethodを実装できます(C ++ではプライベート仮想メソッドを上書きできます)。これはあなたの例では問題ではありませんが、SomePrivateMethodが仮想として宣言されている場合は問題になります

pimplを使用した場合は、PrivatePointの単体テストも簡単に実行できます。

于 2012-09-21T09:10:19.350 に答える
0

いいえ、とにかく、基本クラスを宣言するヘッダーファイルを公開する必要があります。プライベート継承は、データ/メソッドへの不要なアクセスからあなたまたはあなたのユーザーを保護します。

于 2012-09-21T01:49:08.880 に答える