«Практически, сделайте все ваши методы виртуальными» в C ++ - здравый совет? - PullRequest
15 голосов
/ 12 марта 2012

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

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

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

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

Ответы [ 5 ]

13 голосов
/ 13 марта 2012

Есть что-нибудь к этому?

Совет: ПЛОХОЙ , в этом нет сомнений.Чтение чего-то подобного было бы достаточно, чтобы держаться подальше от книги и ее автора.

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

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

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

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

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

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

12 голосов
/ 12 марта 2012

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

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

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

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

3 голосов
/ 12 марта 2012

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

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

0 голосов
/ 12 марта 2012

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

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

0 голосов
/ 12 марта 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...