Подтвердить что ты не робот

"Как правило, сделайте все ваши методы виртуальными" на С++ - здравый совет?

Я только что сделал это в заявлении в названии. Полная цитата:

Как правило, сделайте все ваши методы виртуальными (включая деструктор, но не конструкторы), чтобы избежать проблем, связанных с исключение ключевого слова virtual.

Я нашел это в книге Wrox Professional С++. Вы можете проверить его.

Есть ли что-нибудь для этого? Я бы подумал, что вы предоставите только выделенные точки расширения, а не расширяемость по умолчанию. Например, статья 2001 года Herb Sutter говорит так. С тех пор что-то резко изменилось, чтобы сделать противоположную господствующую норму? (Обратите внимание, что я С++ noob, поэтому я не обсуждал последнее десятилетие.)

4b9b3361

Ответ 1

Есть ли что-нибудь для этого?

Совет БЕСПЛАТНО, о нем нет никаких сомнений. Чтения чего-то подобного было бы достаточно, чтобы держаться подальше от книги и ее автора.

Вы видите, что виртуальное ключевое слово указывает "вы можете или должны переопределить этот метод - он был разработан для этого".

Для любой нетривиальной задачи я не могу представить разумную систему классов, которая позволила бы пользователю (т.е. другому программисту) переопределять каждый отдельный метод в каждом производном классе. Нормально иметь базовый абстрактный класс только с виртуальными методами. Однако, как только вы начинаете создавать производные классы, нет никаких оснований для пошатывания "виртуального" на все - некоторые методы не должны быть расширяемыми.

Создание виртуального означает, что в любой точке кода, независимо от того, какой метод вызывается, вы никогда не можете быть уверены, что класс будет делать то, что вы хотите, потому что кто-то мог бы переопределить ваш метод, нарушив его в процессе к Мерфи-закону это произойдет). Это сделает ваш код ненадежным и будет трудно поддерживать. Еще одна интересная вещь - то, как виртуальные методы вызывают в конструкторах. В основном, следуя этим советам, вы жертвуете удобочитаемостью/надежностью кода в обмен на то, что не делаете довольно необычную опечатку. На мой взгляд, это не стоит.

Для сравнения, не виртуальный метод гарантирует, что независимо от того, что происходит, на этом этапе кода код всегда будет работать так, как вы ожидаете (не считая ошибок, которые вы еще не обнаружили). То есть кто-то другой не заменит ваш метод сломанной альтернативой.

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

Вместо того, чтобы следовать этому "виртуальному" совету, я бы рекомендовал придерживаться закона Мерфи и Принцип KISS. Они работали хорошо для меня. Тем не менее, они не гарантированно хорошо работают для всех остальных.

Ответ 2

Я не согласен с этим принципом.

В прошлом некоторые были обеспокоены чрезмерным использованием virtual из-за проблем с производительностью. Это по-прежнему несколько справедливо, но не слишком проблематично на сегодняшнем оборудовании. (Имейте в виду, что большинство других языков в настоящее время несут аналогичные штрафы. Например, 400MHz iPhone 2G использует Objective C, который вызывает вызов виртуального метода при каждом вызове функции.)

Я думаю, что вы должны использовать virtual только в тех методах, где кажется полезным и разумным отказаться от него в подклассе. Для меня это служит подсказкой для других программистов (или вашего будущего себя) как "это место, где подклассы могут разумно настраивать поведение". Если замена метода в подклассе была бы запутанной или странной для реализации, не используйте virtual.

Кроме того, для простых сеттеров и геттеров это, вероятно, плохая идея, так как она будет препятствовать встраиванию.

Ответ 3

Будет небольшая потеря производительности и потеряно несколько байт памяти.

Реальная проблема заключается в том, что он делает код менее ремонтопригодным, потому что вы говорите что-то о функции, которая не соответствует действительности. Это может вызвать много путаницы.

Ответ 4

Это не может повредить. Если у вас нет подкласса, который переопределяет функцию, ничего не изменится. Я вижу, что этот метод полезен, если у вас много наследования, и вы можете потерять информацию о том, какие классы наследуют, какие.

Лично я не делаю каждый метод класса виртуальным... но это только я. Наличие всего virtual, кажется, делает вещи более запутанными, imho.

Ответ 5

IMHO, это хорошее эмпирическое правило для начинающих с С++. Это не очень вредно, за исключением особых сценариев (с которыми сталкиваются программисты, которые точно знают, что такое компромиссы с виртуальным ключевым словом), и об этом меньше думать.

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