Простого правила не существует:
Использовать 1 (пустая реализация), если для некоторых производных классов имеет смысл ничего не делать, если вызывается функция.
Использовать 3, если нетДля производного класса не имеет смысла не реализовывать функцию.
Используйте 2 в редком случае, когда предварительным условием функции является то, что другая виртуальная функция вернула true, и эта функция имеет реализацию по умолчанию, которая возвращает false(Или что-то вдоль этих линий).В основном, если часть интерфейса является необязательной.(Но обычно в таких случаях лучше получить интерфейс; классы, реализующие расширенный интерфейс, получают его, и клиенты, желающие использовать его dynamic_cast
для расширенного интерфейса.)
Из опыта (но ваше программированиестиль может быть другим), 1, кажется, применяется по крайней мере 90% времени, и я думаю, что за двадцать лет C ++ я использовал 3 один раз, или, может быть, дважды.