9

NVI(非仮想インターフェイス)とテンプレートメソッドパターンの違いは何ですか?

それらは非常に似ているように見え、基本的に同じであり、テンプレートが何らかの形でより一般的であるという点で微妙に異なることの両方を読みました。

4

2 に答える 2

15

NVI はイディオム、Template Method はパターンです。NVI は、C++ での動的ディスパッチを使用したテンプレート メソッド パターンの実装です。テンプレート メタプログラミングを使用して C++ でテンプレート メソッドを作成し、動的ディスパッチをなくすこともできます。

パターンはイディオムよりも一般的であり、言語はパターンを実装するために異なるイディオムを使用する場合があります。

于 2010-06-20T10:11:35.990 に答える
11

すでに述べたように、NVI は言語のカテゴリに関連するプログラミング イディオムです。契約の実施に役立つため、特に Herb Sutter によって推進されています。

  • クラス不変式
  • 関数契約 (渡されたパラメーターと生成された戻り値に対するアサーション)
  • 反復操作 (ロギングなど)
  • 生成された例外を制御します(悪い考えですが;))

ただし、実装は実際にはかなり異なる場合があります。たとえば、NVI 実装の別の例は、それを Pimpl と組み合わせることです。

class FooImpl;

class Foo
{
public:
  enum type { Type1, Type2 };

  Foo(type t, int i, int j);

  int GetResult() const;

private:
  FooImpl* mImpl;
};

そして実装のために:

struct FooImpl
{
  virtual ~FooImpl();
  virtual int GetResult() const;
};

class FooType1: public FooImpl
{
public:
  FooType1(int i, int j);
  virtual int GetResult() const;
private:
  /// ...
};

その方が要点をよりよく伝えていることにいつも気づきました。あなたはそれを理解しましたか?

主なポイントはvirtual、実装の詳細です。また、インターフェースで実装の詳細を公開することは、変更したい場合があるため、悪い考えです。

さらに、実装の詳細は、バイナリ互換性を台無しにする傾向があります。たとえばvirtual、クラスに新しいメソッドを追加すると、仮想テーブルのレイアウトが変更され (一般的な実装手法)、バイナリ互換性が損なわれる可能性があります。gcc では、互換性を維持したい場合は、(仮想の中で) 最後に追加するようにする必要があります。

上記の NVI + Pimpl の組み合わせを使用することにより、virtual公開されたクラスにはまったくありません (プライベートでさえありません)。メモリ レイアウトは、下位互換性と上位互換性があります。バイナリ互換を実現しています。

ここでは、一度にいくつかのパターンを使用します。

  • テンプレート方式
  • 戦略(ポインターを自由に交換できるため)
  • ファクトリ (取得する実装を決定するため)
于 2010-06-20T11:11:47.343 に答える