В чем преимущество этого косвенного вызова функции?
Я нашел следующий код в библиотеке:
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_?, но потребителям нужна статическая функция (для эффективности)? Или для шаблона делегирования?