В чем преимущество этого косвенного вызова функции? - PullRequest
8 голосов
/ 19 марта 2009

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

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 ]

10 голосов
/ 19 марта 2009

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

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

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

3 голосов
/ 19 марта 2009

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

См. PDF , PowerPoint , HTML

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

2 голосов
/ 19 марта 2009

Это шаблон шаблона. Метод 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;
};

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

0 голосов
/ 19 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...