roadman wrote:Я уже как-то приводил пример неправильности использования виртуального деструктора. Напомню. XML парсер - миллионы объектов, большинство которых ссылается на ту или иную общую "схему, описание", то есть занимает в памяти 4 байта. Если для "удобства" или "как всегда" сделать деструктор виртуальным получите 8 байт на объект, а теперь умножьте эти дополнительные 4 байта на несколько миллионов. Щедрая плата за то, чтобы не думать.
Да, верно. Но похоже, что подобные случаи экономии памяти - это ЕДИНСТВЕННЫЕ случаи, когда виртуальный деструктор себя не оправдывает. Может быть, Вы можете привести другой недостаток virtual destructors, кроме расходования памяти на поинтер на vtable?
И надо заметить, что класс, где мы НЕ ставим виртуальный деструктор - должен быть довольно небольшим изначально. У нас в компиляторе - похожая ситуация с expressions - типа b[5-i]+c[1]/d[i*7] - их масса в компилируемом коде, а код наших клиентов довольно велик; но всё равно наши expressions имеют виртуальные деструкторы, потому что для нас довольно часто maintainability важнее памяти.
В Вашем примере 4 х миллионы объектов - это ещё десяток-другой мегабайт памяти. Мне не кажется, что сегодня это - критичный параметр; хотя, конечно, задачи бывают самые разные...
Хотя он может имет определенную ценность в кругу людей, зациклившихся на трактовке языка С++, как языка традиционного ООП, т.е. ООП базирующегося на run-time полиморфизме. У людей, умеющих использовать GP (generic programming) свойства С++ такой ответ может вызвать только недоумение. Тем не менее можно запросто встретить интервьюера, ожидающего именно такой "четкий ответ" и считающего все остальные ответы неверными.
Штука в том, что классически виртуальное наследование (в частности, multiple, вирт. д-торы, етц) - считаются признаками "асовского" владения C++, a основа GP - templates - "макросами высокого уровня". Так сложилось исторически. Это раз. И два - полиморфизм всё-таки более "живой"; написать generic container с помощью полиморфизма - достаточно легко; а имплементировать RTTI с помощью GP - будет изрядным геморроем.
Boriskin wrote:AndreyT wrote: Так вот массовое объявление деструкторов виртуальными там, где они не нужны - это ни что иное, как попытка спасти от падения уже разрушенную программу. Это пример одной из самых грубых ошибок, которые могут существовать в С++ программировании (да и не только в С++ программировании).
Это такая же ошибка, как использование невиртуальных деструкторов там, где должны быть виртуальные. Грубо говоря, есть ситуации, когда надо пользовать одно, есть ситуации когда надо пользовать другое. И чего огород городить то?
ИМХО, это не "такая же" ошибка. Использование ведёт к расходу памяти, неиспользование - может привести к крэшу. Теоретически - надо ставить v.dtor только там, где есть виртуальное наследование; практически - it's a good habit.
Boriskin wrote:AndreyT wrote: Существует тенденция полагать, что правильным ответом на вопрос о виртуальных деструкторах является ответ типа "деструкторы должны быть виртуальными всегда" (что можно заметить и в этой дискуссии).
Вопрос формулируется обычно (4 из 4ех моих последних интервью) следующим образом - "в каких ситуация деструктор должен быть виртуальным и почему?" Четкий вопрос -> четкий ответ, соответственно если вас спросят "когда деструктор должен вызываться непосредственно", то и отвечать надо также точно и четко...
ИМХО, отвечать надо чётко, но по максимуму развёрнуто. Т.е., что-то типа "д-тор должен быть виртуальным, если класс предназначен для виртуального наследования, то есть - <краткое объяснение>".
testuser wrote:Довольно часто замечаю, что дискуссии о С++ скатываются к обсуждению деталей, причем часто опытные разработчики не могут сойтись во мнении о казалось бы простой проблеме. Наверное поэтому народ и переходит с C++ на Джаву и другие языки - там споров нет, все сидят и спокойно пишут.
Во-во, это я и имел в виду в прошлом постинге.