Есть ли веская причина не использовать общедоступные виртуальные методы?

Есть ли веская причина не использовать общедоступные виртуальные методы?

Я где-то читал, что нам следует избегать использования общедоступных виртуальных методов, но я хочу подтвердить от экспертов, является ли это действительным утверждением?

3 ответа

Для хорошего и стабильного дизайна API, Non-Virtual-Interface - хорошая идиома.

Я собираюсь обратиться к существующей хорошей литературе по этому вопросу:

Смотрите также эти великолепные ответы:

(У Sumant Tambe есть интригующая матрица последствий для замысла дизайна в его блоге, в котором есть еще несколько моментов, касающихся замысла дизайна.)

Изготовление virtual Функции non-public позволяют базовому классу создавать протокол вокруг них. Если ничего другого, это может быть использовано для некоторого учета / профилирования, требующего инструментария только базового класса. Открытый интерфейс базового класса может быть inline функции просто переадресация на virtual функции. К сожалению, ограничения могут быть смягчены в производных классах, т. Е. Производный класс может предоставить открытый доступ к virtual функция из базового класса.

На самом деле есть еще одна важная причина для virtual функции protected: при перегрузке virtual функции (например, do_put() члены в std::num_put<...>) легко случайно скрыть другие перегрузки, переопределяя только одну из функций. Когда virtual Функции - это и точка настройки, и интерфейс вызова, это может легко привести к неожиданному поведению. Когда virtual функции protected Понятно, что интерфейс вызова и интерфейсы настройки на самом деле разные, и проблема устраняется даже при непосредственном использовании производного класса. virtual функции, вероятно, хотят быть protected разрешить переопределяющим функциям вызывать реализацию по умолчанию из базового класса. Если реализации по умолчанию нет, virtual функция также может быть private,

Этот ответ обсуждает почему virtual функции не должны быть public, Должны ли вы иметь virtual Функции в первую очередь это отдельный вопрос с несколько нетривиальным ответом.

Мне приходит на ум одно: не использование общедоступных виртуальных методов упрощает отделение интерфейса класса от реализации. Скажем, вы предоставляете публичный метод, делающий что-то:

public:
    virtual void DoSth()
    {
    }

Через некоторое время вводится изменение, которое требует инициализации и завершения базового класса, прежде чем что-то делать. Если вы уже вывели из своего класса несколько классов, вам придется изменить их реализации. Но если вы написали это следующим образом:

protected:
    virtual void InternalDoSth()
    {
    }

public:
    void DoSth()
    {
        InternalDoSth();
    }

Это будет только вопрос изменения реализации DoSth:

public:
    void DoSth()
    {
        InitializeSth();
        InternalDoSth();
        FinalizeSth();
    }

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

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