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

проблема в том, что заранее неизвестно, будет-ли такая ситуация, или нет.

Известно. Если у класса нет виртуальных методов, то такой ситуации не будет.

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

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

сложно. Почему? Кто запрещает?

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

Ага, ООП тут нет. Есть удобная автоматическая генерация табличек с указателями на функции. Плюс возможность расширения структур. С помощью чего можно сэмулировать определённую часть ООП, достаточную для большинства задач.

ranka-lee
()

Опять срач развели, а самого главного не написали.

  1. Если у тебя в конструкторе где-то происходит исключение, деструктор объекта не вызывается, однако вызываются деструкторы всех на данный момент полностью инициализированных членов, так же в обратном порядке;
  2. Eсли у тебя в классе хранится сырой указатель, инициализированный в дальнейшем, скажем, new или new[], то автоматически эта память освобождаться не будет, необходим либо явный вызов delete/delete[] в деструкторе, либо (что очень желательно) вместо сырых указателей использовать unique_ptr.
  3. Применительно к выше: стоит помнить, что у shared_ptr нет специализации для массивов, нужно либо стараться использовать unique_ptr, либо указывать явный делитер при вызове конструктора shared_ptr. В C++17 должны починить.
mix_mix ★★★★★
()
Ответ на: комментарий от ranka-lee

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

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

при чём тут вообще struct, если ты сам знаешь, что разницы нет?

Я без тебя знаю, что struct ничем не отличается от class кроме private по дефолту. Но у меня структуры не участвуют в наследовании и вообще не имеют методов. В т.ч. и деструкторов.

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

А нахрена нужны виртуальные деструкторы в классах, которые никогда не будут базовыми

ещё раз: заранее узнать невозможно, что будет в будущем.

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

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

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

В жабе можно и нужно про это забыть

вот и возвращайся в свою жабу. C++ это не ассемблер, а ЯП высокого уровня. Иногда можно сделать исключение из этого правила, и писать на низком уровне, вот только нужно это очень редко. 99% кода можно писать точно также, как на жабе или сишарпе: полностью абстрагируясь от внутреннего «набора байтов». И не только можно, но и нужно, т.к. вообще говоря компилятор может этот «набор байтов» менять по своему усмотрению.

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

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

я против?

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

возвращайся в жабу. Перегибать палку в C++ не нужно. Может выстрелить.

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

ой! чо правда? std::unique_ptr, std::shared_ptr ну и про стандартные контейнеры STL, которые не имеют виртуальных деструкторов тебе уже натыкали.

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

Известно. Если у класса нет виртуальных методов, то такой ситуации не будет.

а если ты потом сделаешь виртуальные методы?

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

Никто не запрещает. Просто ты будешь самозлобным буратиной если сделаешь так.

согласен. Тогда там комментарий должен быть капсом.

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

ООП тут нет.

может ты просто неосилил?

Есть удобная автоматическая генерация табличек с указателями на функции. Плюс возможность расширения структур. С помощью чего можно сэмулировать определённую часть ООП, достаточную для большинства задач.

что ещё нужно? Благословение Кнута?

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

Если у тебя в конструкторе где-то происходит исключение

…то что-то ты сделал не так.

Нужна инициализирующая функция например. Что-бы такой ситуации не было.

либо (что очень желательно) вместо сырых указателей использовать unique_ptr.

тогда new/delete будет закопано в этом unique_ptr. Как и указатель.

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

Вот тот класс, в который ты добавишь виртуальные методы, и будет базовым. Указатели именно на него ты будешь использовать в тех же коллекциях для хранения объектов классов-наследников. :)

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

Есть мнение и не только моё, что это не ООП, а порнография.

срал я на твоё, и не только на твоё мнение. Вы просто не желаете учить матчасть.

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

А никто не мешает иметь методы в структурах.

не мешает. Но зачем?

Можешь считать что класс без виртуального деструтора это такая структура и всё станет на свои места.

мне не нужна такая структура.

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

за то там есть указатели, которые ты не осилил.

Чего там осиливать? Они и в C++ есть.

скажи это Линусу.

Зачем говорить что-то человеку, который практически никогда не аргументирует свою позицию, который только истерит и срет в обсуждениях? =)

И когда создавался linux, с C++ была совсем другая ситуация. Сейчас переползать на кресты ядру совершенно не за чем.

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

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

Речь не об учебных программах с одним-двумя классами. Ты в реальной системе в сотне-другой классов вот так мановением волшебной палочки деструкторы на невиртуальные поменяешь? И ничего не поломается? Вот ты валенок. :-D

Это так толсто, что даже тонко.

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

Это не дженерики, а херня какая-то. Причем совершенно непонятно, почему она называется _Generic, хотя это фактически просто switch по типу.

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

Нельзя потому как такой код заставит процессор стоять и курить примерно 90% времени.

4.2

если ты не умеешь C++, то это твоя проблема.

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

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

да. А утечка будет в производном, где деструктор невиртуальный.

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

за то там есть указатели, которые ты не осилил.

Чего там осиливать?

Указатели позволяют делать всё то, чего тебе не хватает в сишке.

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

А утечка будет в производном, где деструктор невиртуальный.

Если в базовом виртуальный деструктор, то он виртуальный и в производном. Если тебе не нужно разрешать удалять объекты через базовый класс, то деструктор может быть невиртуальным и защищенным.

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

Речь не об учебных программах с одним-двумя классами. Ты в реальной системе в сотне-другой классов вот так мановением волшебной палочки деструкторы на невиртуальные поменяешь?

у тебя 100 классов ОДНОВРЕМЕННО, в одном участке кода работают, да?

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

Указатели позволяют делать всё то, чего тебе не хватает в сишке.

Позволяют. Просто это всегда хуже читается, дольше пишется, дольше отлаживается и пр. Из-за отсутствия в языке развитых средств построения абстракции. Это никакими указателями не заменишь. Я на сишке тоже пишу, если что.

Загляни в код postgres'а или там nginx'а. Клевые проекты, но на код без слез не взглянешь.

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

Потому что удобно.

тем, что не нужно писать public, да?

Мне не важно, я всегда пишу как-то так:

class Foo
{
  private:
    //
  public:
    //
};

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

Просто это всегда хуже читается, дольше пишется, дольше отлаживается и пр.

с виртуальными деструкторами та же история.

emulek
()

рак. деструкторов вообще не надо писать.

class A
{
  private:
    ~A() {}
};

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

Ну этот как написать. :)

class Base
{
public:
	Base() { cout << "Base::Base" << endl; }
	~Base() { cout << "Base::~Base" << endl; }
};

class Child : public Base
{
public:
	Child() { cout << "Child::Child" << endl; }
	// Обрати внимание где мы можем объявить деструктор виртуальным!!!
	virtual ~Child() { cout << "Child::~Child" << endl; }

	virtual	void	foo()	{ cout << "Child::foo" << endl; }
};

class Bar : public Child
{
public:
	Bar() { cout << "Bar::Bar" << endl; }
	~Bar() { cout << "Bar::~Bar" << endl; }

	virtual	void	foo()	{ cout << "Bar::foo" << endl; }
};

int main()
{
	Child *child = new Bar;
	child->foo();
	delete child;

	return 0;
}

Вывод:

Base::Base
Child::Child
Bar::Bar
Bar::foo
Bar::~Bar
Child::~Child
Base::~Base

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

у тебя 100 классов ОДНОВРЕМЕННО, в одном участке кода работают, да?

Нет, а какое это имеет значение?

ключевое. Зачем что-то менять в деструкторе класса, который выполняется всего _один_ раз? На что он влияет?

Виртуальные деструкторы становятся ощутимы лишь в случае, когда они активно вызываются, и при этом они ещё и очень простые. Но такой случай на практике возникает редко, разве-что в классах типа std::string.

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

Т.е. ты решаешь, что эти объекты нельзя объединять в коллекции?

Да, решаю я.

Ну и нафиг нужны такие объекты?

Явно не для того, что бы emulek мог положить такой объект в коллекцию.

хорошее оправдание говнокода.

Пихать virtual туда, где он не нужен - вот это говнокод.

Ну так с дуру можно много чего сломать.

дык зачем пихать пипиську в непонятные и не предназначенные для этого отверстия? Не делай так, и всё будет хорошо.

Весенний спермотоксикоз начался?

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

не осилили ASCIIZ строки, и потому юзаете std::string?

Что еще придумает ваш воспаленный мозг?

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

Пихать virtual туда, где он не нужен - вот это говнокод.

проблема будет в будущем, когда оно внезапно будет нужно.

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

Это — деструктор. Пойди учебник почитай, что-ли.

валенок, я знаю, что это деструктор. Он виртуальный или нет?

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

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

Например, если используется идиома pimpl. Например, вот в таком случае:

class some_class {
  class impl;
  std::unique_ptr< impl > impl_;
public :
  ...
};

Если класс some_class::impl описывается где-то внутри .cpp-файла, не доступного пользователю some_class, а в самом some_class нет деструктора (даже пустого), то компилятор/линкер должен сильно ругнуться.

Хотя если дать определение some_class::impl прямо внутри some_class, то деструктор some_class можно не определять вообще, компилятор его сам сгенерирует.

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

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

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