| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Вызывается ли деструктор? |
| Автор: Riddik 6.5.2009, 00:29 | ||||
| Вопрос, скорее всего, дурацкий, но мне для успокоения Есть два классы, пусть Monstr и Male, в их конструкторе выделяется память, в деструкторе - освобождается. Эти классы помещаются в контейнер типа вектор, содержащий указатель на базовый класс, из которого выведены Monstr и Male:
Затем, когда возникает необходимость, контейнер очищается :
Вопрос: когда очищается контейнер таким способом, вызывается ли деструктор класса Monstr и деструктор класса Male? Другими словами, та память, что выделяется их конструкторами, освобождается? Или для успокоения написать отдельную функцию, которая будет это делать и вызывать её вместе с очисткой контейнера? |
| Автор: mes 6.5.2009, 00:31 |
| Вызов деструктора наследника, будет произведен, только если он помечен виртуальным в базовом. Вектор указателей, при очищении не удаляет объекты. Это Вы должны сделать самостоятельно. исправлено |
| Автор: Riddik 6.5.2009, 00:33 |
| mes, не понял, простите. Если сделать виртуальный деструктор в базовом? |
| Автор: mes 6.5.2009, 00:36 |
да. (в наследниках он автоматическки получится тоже виртуальный.) |
| Автор: Riddik 6.5.2009, 00:41 | ||||
Как же его объявить, возникают ошибки, не хочет компилироваться:
или
? |
| Автор: mes 6.5.2009, 00:45 | ||
Вы ошибки то читаете ? там же ясным языком написано, что нет определения у функции. Или Вы на ощупь программируете ?
|
| Автор: Riddik 6.5.2009, 00:46 | ||
И ещё такой момент, есть просто указать на базовый класс, которому выделяется память на производный из него:
Затем память удаляется: delete p; Естественно, деструктор класса Monstr вызван не будет? То же самое, что с pbase.clear() ? Добавлено через 2 минуты и 56 секунд mes, на ощупь, конечно. Я, если честно, про такие инструкции virtual ~base() {} ничего не знаю ещё. Спасибо Добавлено через 4 минуты и 13 секунд Это так же вызовет деструктор classA и при p=new classA; delete p; ? |
| Автор: Riddik 6.5.2009, 00:59 |
| У функции должно быть тело, а как же чисто виртуальные ф-ии virtual void func()=0; почему не virtual void func() {} Добавлено @ 01:10 поискал в соседней теме - не нашёл, где мне сообщили о решении подобной проблеме, речь шла об абстрактном классе, а проблема была в том, что его наследники получились тоже абстрактными. Про деструкторы и {} там мне ничего не говорили. |
| Автор: J0ker 6.5.2009, 01:10 |
| Riddik, у вас в голове каша учите матчасть |
| Автор: Riddik 6.5.2009, 01:11 |
| J0ker, Да учу я, но и бегу вперёд поезда Добавлено через 1 минуту и 46 секунд :( |
| Автор: J0ker 6.5.2009, 01:17 |
| уясните для начала разницу между pure virtual, virtual и abstract |
| Автор: Riddik 6.5.2009, 01:22 |
| pure virtual, virtual и abstract вы будете смеятся, но в тех книжках, которые я уже прочёл, об этом ни слова Добавлено через 21 секунду вернее только про virtual |
| Автор: J0ker 6.5.2009, 01:24 |
| значит вы читали что-то не по С++ |
| Автор: mes 6.5.2009, 01:26 |
я специально сделал акцент на слово вызываемая. У виртуальных функций, тело связывается с вызовом в рантайме (в отличие от обычных - на этапе линковки). И чтоб не было возможности вызвать функцию, у которой нет связи с телом, нельзя создавать объекты абстрактных классов. Да фраза не совсем корректная, но она намекала на возможный ход мыслей, когда бы Вы прочитали ошибку компилятора. Там написано : не хватает тела функции. Следовательно Вы должны были подумать как объяснить компилятору, где искать. или написать тело или пометить чисто-виртуальной (ну или и то другое, но Вам это рано) P.S У деструктора, тело должно быть всегда, даже когда он помечен, как чистая виртуальная функция. У виртуальных функций, тело может быть не определено, но должнa быть метка "чистоты" . Если у класса есть хоть одна функция, помеченная как "чистая", то объект такого класса нельзя создать. |
| Автор: Riddik 6.5.2009, 01:26 |
| Купник. Изучаем С++ Франка. Самоучитель С++ Шилдт. Базовый курс С++ Добавлено через 1 минуту и 41 секунду mes, спасибо большое |
| Автор: mes 6.5.2009, 01:29 |
так тоже можно, чистые функции объявляются для того, если хотите использовать указатель на базовый класс как интерфейс, и объект подобного типа Вам не нужен. |
| Автор: Riddik 6.5.2009, 01:35 |
| mes, ещё раз спасибо за объяснения! Значит в любом случае у деструктора должно быть тело ф-ии, даже если это чисто-виртуальный деструктор в абстрактном классе. P.S. Понимаю, что опытных программистов должно бы быть раздражает, когда говорят такие вещи, как я говорил здесь про память и указатели на неё, вроде "укзатель на базовый класс, ему выделяется память" - на самом деле уж это я понимаю, что выделяется память и адрес этой памяти присваивается указателю, а сказал небрежно, каюсь |
| Автор: mes 6.5.2009, 01:42 | ||||
Да.
Создается объект. А выделение памяти это всего лишь один из этапов создания объекта. |
| Автор: Riddik 6.5.2009, 01:52 |
| Не буду умничать |
| Автор: Riddik 6.5.2009, 02:07 | ||
с delete всё нормально - вызывается деструктор, в если очищать вектор - не вызывается
Результат: выводит по пять строк "This is constructor А" и "This is constructor B", деструктор молчит. А если base *p=new A; затем delete p, то всё нормально, деструктор A вызывается |
| Автор: mes 6.5.2009, 02:13 |
естественно, В векторе Вы храните указатели, а не объекты. За удаление "реальных" объектов он не отвечает. |
| Автор: Riddik 6.5.2009, 02:16 |
| Не понял, во втором сообщении Вы же ответили "только если он виртуальный в базовом" на вопрос "когда очищается контейнер таким способом, вызывается ли деструктор класса Monstr" Сорри, уже поздно, наверное я плохо понимаю |
| Автор: mes 6.5.2009, 02:26 |
сорри за невнимательность и за то что ввел в заблуждение, я там ответил только на половину вопроса - исправил. Ага, и на меня тоже сказывается |
| Автор: Riddik 6.5.2009, 02:32 | ||
| Ясно Вот так нормально самому память освобождать:
|
| Автор: mes 6.5.2009, 02:40 |
| да |
| Автор: Riddik 6.5.2009, 02:42 |
| Тогда вопрос решён - спасибо за всё |
| Автор: azesmcar 6.5.2009, 08:58 | ||||
вот так будет универсальнее, напишите функтор
вызов
будет работать для любого (STL совместимого) контейнера |
| Автор: Riddik 6.5.2009, 10:03 |
| azesmcar, благодарю. |