В чем преимущество этого косвенного вызова функции?

Я нашел следующий код в библиотеке:

class Bar {
public:
  bool foo(int i) {
   return foo_(i);
  }
private:
  virtual bool foo_(int i) = 0;
};

Теперь я задаюсь вопросом: почему вы используете это косвенное обращение? Могут ли быть причины, по которым вышесказанное будет лучше, чем простая альтернатива:

class Bar {
public:
  virtual bool foo(int i) = 0;
};

4 ответа

Решение

Это идиома невиртуального интерфейса (NVI). На этой странице Херба Саттера есть немало подробностей. Тем не менее, умерить то, что вы читаете там, тем, что C++ FAQ Lite говорит здесь и здесь.

Основным преимуществом NVI является отделение интерфейса от реализации. Базовый класс может реализовывать общий алгоритм и представлять его миру, в то время как его подклассы могут реализовывать детали алгоритма через виртуальные функции. Внешние пользователи защищены от изменений в деталях алгоритма, особенно если позже вы решите добавить код до и после обработки.

Очевидным недостатком является то, что вы должны написать дополнительный код. Также, private виртуальные функции сбивают с толку многих людей. Многие программисты ошибочно полагают, что вы не можете их переопределить. Херб Саттер, кажется, нравится private виртуальные, но имхо на практике эффективнее следовать рекомендациям C++ FAQ Lite и делать их protected,

Это шаблон шаблона. Метод foo содержит код, который должен выполняться всеми подклассами. Это имеет больше смысла, когда вы смотрите на это так:

class Bar {
public:
  bool foo(int i) {
   // Setup / initialization / error checking / input validation etc 
   // that must be done for all subclasses
   return foo_(i);
  }
private:
  virtual bool foo_(int i) = 0;
};

Это лучше, чем альтернатива, которая заключается в том, чтобы не забыть вызывать общий код в каждом подклассе индивидуально. Неизбежно, кто-то создает подкласс, но забывает вызывать общий код, что приводит к любому количеству проблем.

Это часто называют парой Шаблон-Крюк (также известной как Горячая точка), придуманной Вольфгангом При.

Смотрите этот PDF, PowerPoint, HTML

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

Если подкласс может изменить определение foo_?, но потребителям нужна статическая функция (для эффективности)? Или для шаблона делегирования?

Другие вопросы по тегам