LINUX.ORG.RU

С++ поведение деструктора?

 


0

3

Здравствуйте. Возник вопрос надеюсь вы сможете помочь. Деструктор по умолчанию в С++ вызывает деструкторы всех членов данных объявленных в классе. Если я определю деструктор например:

class A{
  std::vector<MyClass> V_;
  int num_;
public:
  A(){};
  ~A(){
    std::cout<<"Hello, World\n";
  }
}
при вызове деструктора объекта класса А будут вызваны детструкторы V_ и num_? Заранее благодарю.



Последнее исправление: mgalimullin (всего исправлений: 3)
Ответ на: комментарий от emulek

Коллекции здесь вообще не причем. Постарайся подумать.

Вот простой пример:

class base
{
public:
    void foo();
    void bar();
};

class child : public base
{
public:
    void method();
};

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

base *ptr = new child;    // ???

Ну только если ты не просто извращенец, любящий заниматься привидением типов. :)

BRE ★★
()
Ответ на: комментарий от emulek

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

ranka-lee
()
Ответ на: комментарий от Gvidon

Какое отношение шаблонность вектора имеет к отсутствию у него виртуального деструктора?

полиморфизм std::vector достигается не наследованием, а разворачиванием шаблона по-месту. Потому для шаблонов виртуальный деструктор не нужен.

Вообще говоря, отсутствие виртуального деструктора в шаблонах STL — тоже накладные расходы.

emulek
()
Ответ на: комментарий от emulek

За кой ляд они вообще на C++ писали?

А в C++ всегда так: даже реализация простых списков на шаблонах тоже не настолько оптимальна, как реализация на чистой сишке. За абстракции всегда нужно платить.

За столько лет ты так и не понял суть C++. С твоей парадигмой использования C++ тебе надо просто взять Java и не париться.

i-rinat ★★★★★
()
Ответ на: комментарий от emulek

Поэтому тебе написали про protected.

костыль.

Костыль потому что ты не умеешь проектировать софт и везде лепишь виртуальный деструктор?

ответил. В моих структурах нет методов. Вообще.

Тем ни менее их можно наследовать друг от друга.

anonymous
()
Ответ на: комментарий от i-rinat

Если тебе не нужно держать объекты в структурах, зачем тебе тогда вообще C++?

в C++ есть ещё и классы, валенок.

emulek
()
Ответ на: комментарий от ranka-lee

Потому что в C нет некоторых полезных вещей вроде шаблонов.

тебе, как я погляжу, не шаблоны нужны, а STL. Что-бы сделать из C++ некое подобие php.

emulek
()
Ответ на: комментарий от emulek

Никто тебе не запрещает отнаследоваться от вектора и сделать свой супер-пупер контейнер на его основе. Но виртуального деструктора всё равно нет. Почему?

Gvidon ★★★★
()
Ответ на: комментарий от ranka-lee

Ага. Но то даже без delete.

если в деструкторе нет delete и/или других нетривиальных зачисток ресурсов, то зачем вообще нужен деструктор? «чтоб был»? Ок, поправка: если деструктор нахрен не нужен, то он может и НЕ быть виртуальным.

emulek
()
Ответ на: комментарий от emulek

А как же наследование? То что вы что то наследуете ещё не значит что там есть delete. То же самое и с его отсутствием - если деструктора нет то это ещё не значит что нет зачисток. Делать виртуальный дестурктор просто так, чтобы был, идотизм достойный обучения силикатным кирпичом.

ranka-lee
()
Ответ на: комментарий от BRE

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

что-бы писать код, который может работать с каким-то class'ом, но при этом неизвестно, с каким именно. Это альтернатива шаблонам. Иногда шаблон лучше, иногда — хуже.

Одно однозначно: если ты решил делать полиморфный тип, то у тебя два варианта:

1. сделать шаблон. Тут естественно виртуальных функций не нужно, в т.ч. и деструкторов, иначе нет никакого смысла в шаблоне.

2. сделать базовый класс, и работать с базовым классом. Вот тут деструктор должен быть виртуальным.

emulek
()
Ответ на: комментарий от ranka-lee

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

Это best practices.

emulek
()
Ответ на: комментарий от i-rinat

За столько лет ты так и не понял суть C++. С твоей парадигмой использования C++ тебе надо просто взять Java и не париться.

объясни мне, непутёвому «суть C++». Жду с нетерпением…

emulek
()
Ответ на: комментарий от emulek

в C++ есть ещё и классы, валенок.

Если в структуре есть объекты, ты объявляешь её классом? Вот ты валенок. :-)

Придумал себе правила, и всё, что этим правилам не подчиняется, считаешь «неправильным C++». Как, в общем, и с остальными понятиями. Ещё и других учить пытаешься.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

ответил. В моих структурах нет методов. Вообще.

Тем ни менее их можно наследовать друг от друга.

не забудь написать

// ВНЕЗАПНО
в коде. Пусть все знают, какие русские — мудаки.

emulek
()
Ответ на: комментарий от emulek

2. сделать базовый класс, и работать с базовым классом. Вот тут деструктор должен быть виртуальным.

Вот тебе и пытаются все донести, что если ты не хочешь делать полиморфный тип, то ты не делаешь виртуальные методы, соответственно тебе не нужен виртуальный деструктор вместе с vtbl. :)

BRE ★★
()
Ответ на: комментарий от Gvidon

Никто тебе не запрещает отнаследоваться от вектора и сделать свой супер-пупер контейнер на его основе. Но виртуального деструктора всё равно нет. Почему?

а почему в php всего одна единственная коллекция? Понятно почему: если в php сделать 3 коллекции, то обезьянки-кодеры запутаются. Потому сделали одну, которая хоть и плохо, но подходит ко всем случаям. Также и в STL — сделали то, что попроще, но в отличие от php, ты можешь создать my::vector, с виртуальными деструкторами и сборкой мусора.

emulek
()
Ответ на: комментарий от emulek

суть C++

Тут всё просто, но боюсь, что ты всё равно не поймёшь. C++ нужен там, где всё ещё важна скорость работы, но объём кода и сложность предметной области делают разработку на C слишком дорогой в финансовом и временном смыслах.

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

Если ты решаешь (предположим, что ты в проекте главный и принимаешь решения), что безопасность кодирования важнее производительности, и вводишь правила об обязательности виртуальных методов, ты теряешь преимущества C++ перед другими языками. Просто выбери Java, C# или другой понравившийся язык, в котором нет необходимости думать о памяти или накладных расходах на вызов метода. Это просто лишняя нагрузка из-за «ололо, я крутой и использую С++», реальной пользы от неё уже нет.

i-rinat ★★★★★
()
Ответ на: комментарий от ranka-lee

То же самое и с его отсутствием - если деструктора нет то это ещё не значит что нет зачисток.

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

К примеру, только виртуальные деструкторы будут раскручиваться при обработке исключений, которые по сути своей происходят ВНЕЗАПНО. Дело в том, что в момент исключения у объектов может и не быть информации о действительном типе объекта. Очень возможно, что в момент исключения мы будем располагать лишь указателем типа базового класса. Предлагаешь тащить за собой действительный тип объекта? Дык для того VT и придумали, что-бы действительный тип был всегда под рукой.

emulek
()
Ответ на: комментарий от i-rinat

Если в структуре есть объекты, ты объявляешь её классом? Вот ты валенок

ЩИТО?

Придумал себе правила

про деструктор — это не я придумал.

Про структуры: что ты мне опять какой-то свой неструктурированный бред приписываешь? Ты уж определись, что там думает придуманный тобой emulek о структурах.

emulek
()
Ответ на: комментарий от emulek

придуманный тобой emulek

А реальный emulek вообще о чём-то думает? Ты же забываешь даже то, что сам писал, а когда тебе ссылку дают, делаешь вид, что не видишь.

ЩИТО?

Если долго прикидываться валенком, станешь валенком, вот щито.

неструктурированный

Почему неструктурированный? Классический. :-D

про деструктор — это не я придумал.

Есть такие рекомендации, да. Но вот применять их «ВСЕГДА» — это ты придумал сам себе. И ещё ходишь другим советуешь.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 2)
Ответ на: комментарий от emulek

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

Gvidon ★★★★
()
Ответ на: комментарий от BRE

Вот тебе и пытаются все донести, что если ты не хочешь делать полиморфный тип

любой класс может стать полиморфным. Что-бы узнать доподлинно, нужно видеть будущее. Лучше уж сразу сделать деструктор виртуальным, дабы не возникло проблем в будущем.

emulek
()
Ответ на: комментарий от metawishmaster

для num_ не вызовется, это ж int - простейший тип, у которого не {кон/де}структора

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

mix_mix ★★★★★
()
Ответ на: комментарий от emulek

Если у него нет виртуальных методов, то никто не будет использовать указатель на него для адресации объектов дочерних классов. Неужели это так сложно понять? 8)

BRE ★★
()
Ответ на: комментарий от emulek

Деструктор ВСЕГДА должен быть виртуальным

Orly?!

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

pon4ik ★★★★★
()
Ответ на: комментарий от i-rinat

Оптимизации типа выбора виртуальных или не виртуальных деструкторов не являются преждевременными. Они производятся во время фазы проектирования.

К сожалению, это верно лишь для придуманного идеального мира. В реальном мире всё хуже. Проектировщиков, способных предвидеть будущее не существует. Увы.

Причина проста — они никогда не выползут в профилировщике, так как размазаны равномерно по всему коду. Тормоза от неверного выбора алгоритма сортировки ты увидишь, а тормоза от виртуальных функций — нет.

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

Просто выбери Java

это ты не понял сути C++. А суть в том, что C++ позволяет _нарушать_ правила. Деструктор, как правило должен быть виртуальным, однако, в 0.1% случаев есть смысл его делать НЕ виртуальным, к примеру если мне нужен массив из 100500 классов(с одним полем из 4х байтов), причём VT в этих классах не нужна. В жабе я буду плакать, и жрать кактус, в C++ я сделаю НЕ виртуальный деструктор.

emulek
()
Ответ на: комментарий от i-rinat

Просто выбери Java, C# или другой понравившийся язык, в котором нет необходимости думать о памяти или накладных расходах на вызов метода. Это просто лишняя нагрузка из-за «ололо, я крутой и использую С++», реальной пользы от неё уже нет.

типичная ошибка новичков: _всегда_ думать о накладных расходах. Проблема в том, что в 99.9% случаев, эти накладные расходы не имеют никакого значения. А вот сложность поддержки _всегда_ имеет значение.

Если уж ты видишь, что VT так тормозит, то убери VT, в чём проблема? Если код дьявольски сложен, и ты не видишь, то очевидно, что тормозит не VT, а твоя дьявольски сложная логика.

emulek
()
Ответ на: комментарий от Gvidon

потому что наследоваться от стандартных контейнеров — быдлокод?

anonymous
()
Ответ на: комментарий от emulek

Нет, не любой. Класс это тупой кусок памяти в котором мы знаем где что лежит и связанные с ним функции для манипуляции с привилегиями знать смещения до них. Отличие от структуры только в том что кишки по умолчанию private. И всё.

ranka-lee
()
Ответ на: комментарий от i-rinat

А реальный emulek вообще о чём-то думает? Ты же забываешь даже то, что сам писал, а когда тебе ссылку дают, делаешь вид, что не видишь.

я всё помню. А ссылки ты даёшь совершенно не в тему. Просто вырываешь из контекста обсуждения какую-то мою реплику, и радуешься «вот emulek говорил, в огороде бузина!», и ничего, что обсуждается дядька из Киева.

Есть такие рекомендации, да. Но вот применять их «ВСЕГДА» — это ты придумал сам себе. И ещё ходишь другим советуешь.

Это правило. Из него есть исключения. Но ТСу про них знать рано. Тебе видимо тоже.

emulek
()
Ответ на: комментарий от Gvidon

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

проблема в том, что заранее неизвестно, будет-ли такая ситуация, или нет. Сегодня нет, а через год такая ситуация возникнет, и приложение потечёт. И ты потратишь Over9000 часов на поиск этого места.

Невиртуальный деструктор — потенциальный(в лучшем случае) баг.

emulek
()
Ответ на: комментарий от emulek

Если у класса нет вирутального деструктора то у него нет базового класса, и он сам не может быть базовым классом. Вот и вся история. Это тупая удобная обёртка над набором байтиков. ООП головного мозга надо лечить.

А если ты унаследовался от него - то сам себе злобный буратина. Хорошо что теперь есть слово «final» позволяющее буратин ставит на место.

ranka-lee
()
Последнее исправление: ranka-lee (всего исправлений: 1)
Ответ на: комментарий от Gvidon

Стандартная библиотека — это уже очень давно часть языка и разрабатывается она теми же людьми.

почему ты strcpy(3) не юзаешь для строк в C++? Оно тоже в стандарте есть.

emulek
()
Ответ на: комментарий от emulek

Это правило.

Чье? Кто придумал? Емулёк? А кто он такой?

http://www.gotw.ca/publications/mill18.htm

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

Речь идет о базовых классах. А нахрена нужны виртуальные деструкторы в классах, которые никогда не будут базовыми, известно только каком-то емулёку. Зато понятно откуда столько тормозящего говнокода на крестах.

anonymous
()
Ответ на: комментарий от Gvidon

Абсолютно всё внутри есть набор байтов. Это надо всегда понимать если имеешь дело с C++. В жабе можно и нужно про это забыть и думать что ты имеешь дела с некими объектами. Тут нельзя.

ranka-lee
()
Ответ на: комментарий от emulek

почему ты strcpy(3) не юзаешь для строк в C++?

Кто сказал, что не использую? Иногда и использую, там где это нужно.

Gvidon ★★★★
()
Ответ на: комментарий от emulek

Кстати одна из хороших практик в C++ и вообще - это ограничение глубины наследования. В идеале наследоваться должно быть возможным только от интерфейсов.

ranka-lee
()
Ответ на: комментарий от ranka-lee

Абсолютно всё внутри есть набор байтов.

Да, но программист далеко не всегда знает и имеет право предполагать, как именно эти байтики расположены. Даже в C++

Gvidon ★★★★
()
Ответ на: комментарий от Gvidon

для POD типов знает и имеет право.

а вот при добавлении VT уже да, не знает, потмоу как компилятор в этом случае волен расставлять как хочет.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.