C ++: Разница между NVI и шаблонными методами? - PullRequest
7 голосов
/ 20 июня 2010

В чем разница между NVI ( Не виртуальный интерфейс ) и Шаблонный метод шаблоны?

Они кажутся очень похожими, и я прочитал, что они в основном одинаковы, и что они слегка отличаются, так как Template как-то более общий.

Ответы [ 2 ]

11 голосов
/ 20 июня 2010

NVI - это идиома, Template Method - это шаблон. NVI - это реализация Pattern Template Pattern, использующая динамическую диспетчеризацию в C ++; также возможно создать шаблонные методы в C ++, используя шаблонное метапрограммирование, чтобы исключить динамическую диспетчеризацию.

Шаблон является более общим, чем идиома, и языки могут использовать разные идиомы для реализации шаблона.

9 голосов
/ 20 июня 2010

Как уже было сказано, NVI - это идиома программирования, относящаяся к категории языков.Он был продвинут Хербом Саттером среди других, потому что он помогает обеспечить соблюдение контрактов:

  • инварианты класса
  • контракты функций (утверждения относительно переданных параметров и сгенерированного возвращаемого значения)
  • повторяющиеся операции (например, ведение журнала)
  • контроль над сгенерированными исключениями (плохая идея;))

Однако реализация может на самом деле значительно отличаться, например, другой пример 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 вообще нет (недаже личное) в классе выставлено.Расположение памяти обратно и вперед совместимо.Мы достигли бинарной совместимости.

Здесь мы используем несколько шаблонов одновременно:

  • Шаблонный метод
  • Стратегия (поскольку мы можем менять указатель по желанию)
  • Фабрика (чтобы решить, какую реализацию мы получим)
...