8

я нашел следующий код в библиотеке:В чем преимущество этого непрямого вызова функции?

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; 
}; 

ответ

10

Это Non-Virtual Interface Idiom (NVI). На этой странице у Херба Саттера есть много деталей об этом. Тем не менее, нравятся то, что вы читаете там, с тем, что говорит C++ FAQ Lite: here и here.

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

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

3

Это часто называется Template-Hook пара (a.k.a Hotspot), придуманный Вольфгангом Pree.

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

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

0

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

2

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

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