Есть ли веская причина не использовать общедоступные виртуальные методы?
Есть ли веская причина не использовать общедоступные виртуальные методы?
Я где-то читал, что нам следует избегать использования общедоступных виртуальных методов, но я хочу подтвердить от экспертов, является ли это действительным утверждением?
3 ответа
Для хорошего и стабильного дизайна API, Non-Virtual-Interface - хорошая идиома.
Я собираюсь обратиться к существующей хорошей литературе по этому вопросу:
Смотрите также эти великолепные ответы:
- Какой смысл частной чисто виртуальной функции?
- Вызовите метод базового класса C++ автоматически
- Лучший способ объявить интерфейс в C++11
- Как обеспечить, чтобы вызовы виртуальных методов распространялись вплоть до базового класса?
- В чем преимущество этого косвенного вызова функции?
(У 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();
}
Создание двухуровневых виртуальных функций очень дешево и предоставляет вам дополнительный уровень, который позволяет легко контролировать способ вызова виртуального метода в будущем.