|
|
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Есть класс A, в котором генерируется исключение. Класс B наследуется от него. В обоих классах имеются данные, которые необходимо уничтожить при вызове этого исключения. Понятно, что это можно сделать какой-нибудь виртуальной функцией функцией. А что делать, если нужно вызвать деструктор? Прямой вызов в классе A деструктора this->~A() естественно не вызовет деструктор ~B(), как хотелось бы. Есть ли возможность это сделать? или вообще никак нельзя? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 19:32 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
А что делать, если нужно вызвать деструктор? Прямой вызов в классе A деструктора this->~A() естественно не вызовет деструктор ~B(), как хотелось бы. Есть ли возможность это сделать? или вообще никак нельзя? непосредственный вызов деструктора используется в крайне редких случаях, вряд ли вам это нужно так что два варианта: виртуальный метод очистки, либо ловим в B исключение чистим что надо и дальше его кидаем особо отмечу случай если исключение происходит в конструкторе ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:03 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLg пишет: > Понятно, что это можно сделать какой-нибудь виртуальной функцией > функцией. А что делать, если нужно вызвать деструктор? Прямой вызов в > классе A деструктора this->~A() естественно не вызовет деструктор ~B(), > как хотелось бы. Есть ли возможность это сделать? или вообще никак нельзя? Просто удали объект. Все будет хорошо, деструктор B вызовется сам. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:13 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
в B мы можем отловить ислючение только в случае, если метод из А вызываем методом из B. Да и то это проходит только для обычных методов. А вот, к примеру (как Вы правильно отметили - у меня так и происходит :) ), если исключение вызывается в конструкторе - то в конструкторе B его уже никак не отловить:( Так что для ситуации, когда B наследует несколько классов, парочка из них инициализируется, а потом A генерит exeption, то получается утечка памяти в тех классах, которые остались без вызова деструктора. Кстати, а что, есть возможность отловить исключение производным классом, как бы оно не генерировалось в базовом? По-моему такого способа нет. Только если функция базового вызывается из функции производного. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:14 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
MasterZiv StepLg пишет: > Понятно, что это можно сделать какой-нибудь виртуальной функцией > функцией. А что делать, если нужно вызвать деструктор? Прямой вызов в > классе A деструктора this->~A() естественно не вызовет деструктор ~B(), > как хотелось бы. Есть ли возможность это сделать? или вообще никак нельзя? Просто удали объект. Все будет хорошо, деструктор B вызовется сам. Posted via ActualForum NNTP Server 1.4 и как же его удалить? ) из основного кода? Не хорошо получается. Опять же, ситуация, когда исключение генерится в конструкторе одного из базовых объектов класса. Получается, что часть объектов уже инициализирована, а часть еще нет. Вызывать деструктор для всех подряд - смерти подобно. Не вызывать совсем - черевато утечкой памяти. Причем виртуальная функция очистки объектов здесь не пройдет никак. (почему - объяснять или нет?) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:17 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
кстати, просто удалить объект нельзя. он же по сути не существует. После исключение в конструкторе A конструктор B не вызывается, а значит объект B не существует. (интересно, а существует ли объект A - успел он создаться по стандарту или нет... это тоже тот еще вопрос). Поэтому никакие методы, включая деструктор, у B вызывать нельзя. Кстати, это причина, по которой нельзя пользоваться виртуальностью. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:29 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLgкстати, просто удалить объект нельзя. он же по сути не существует. После исключение в конструкторе A конструктор B не вызывается, а значит объект B не существует. (интересно, а существует ли объект A - успел он создаться по стандарту или нет... это тоже тот еще вопрос). Поэтому никакие методы, включая деструктор, у B вызывать нельзя. Кстати, это причина, по которой нельзя пользоваться виртуальностью. Запусти вот это и посмотри на вывод, все вопросы отпадут. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 20:47 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLg пишет: > в B мы можем отловить ислючение только в случае, если метод из А > вызываем методом из B. Да и то это проходит только для обычных методов. > А вот, к примеру (как Вы правильно отметили - у меня так и происходит :) > ), если исключение вызывается в конструкторе - то в конструкторе B его > уже никак не отловить:( Почему не отловить ? внутри тела констуктора лови сколько хочешь. > Так что для ситуации, когда B наследует несколько классов, парочка из > них инициализируется, а потом A генерит exeption, то получается утечка > памяти в тех классах, которые остались без вызова деструктора. Такого не может быть. Если при вызове конструктора выбрасывается исключение, C++ правильно вызывает все деструкторы и удаляет память (если объект создавался в динамической памяти). В ситуации, когда B наследуется от нескольких классов, и при инициализации одного из подъобъектов выбрасывается exception, С++ корректно вызовет деструкторы всех подъобъектов, которые к этому времени уже успели проинициализироваться, и никакая память никуда не утечет, если деструкторы написаны правильно. > Кстати, а что, есть возможность отловить исключение производным классом, > как бы оно не генерировалось в базовом? По-моему такого способа нет. > Только если функция базового вызывается из функции производного. Исключения не зависят от наследования. Они зависят от стека вызовов функций. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 21:02 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLg пишет: > Просто удали объект. Все будет хорошо, деструктор B вызовется сам. > и как же его удалить? Если ты не понимаешь, приведи свой код, может кто-то что-то и скажет. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 21:03 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLg пишет: > кстати, просто удалить объект нельзя. он же по сути не существует. После > исключение в конструкторе A конструктор B не вызывается, а значит объект > B не существует. Неправильно. Объект существует, но не проинициализирован. > никакие методы, включая деструктор, у B вызывать нельзя. Кстати, это > причина, по которой нельзя пользоваться виртуальностью. Чего ?? Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 21:04 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. выводит: G() B() A() 0 A() 1 A() 2 A() 3 A() 4 A() 5 A() 6 THROW!!!! terminate called after throwing an instance of 'int' Aborted ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 21:35 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
а.. все. если в мейне добавить try блок, то G() удалится нормально. а A мы можем и самостоятельно деинициализировать до выброса исключения :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 21:38 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLg пишет: > а.. все. > если в мейне добавить try блок, то G() удалится нормально. а A мы можем > и самостоятельно деинициализировать до выброса исключения :) Ты так ничего и не понял. G удалится нормально В ЛЮБОМ СЛУЧАЕ. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 22:19 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
MasterZiv G удалится нормально В ЛЮБОМ СЛУЧАЕ. Posted via ActualForum NNTP Server 1.4 Ой, и мне объясни тогда, почему нет печати из деструктора G. Я не совсем вкурил. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 23:17 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLgа.. все. если в мейне добавить try блок, то G() удалится нормально. а A мы можем и самостоятельно деинициализировать до выброса исключения :) Будь добр, приведи пример, чего ты собрался самостоятельно деинициализировать. Есть предположение, что оно работать не будет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.04.2007, 23:19 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Хотите я открою вам страшную тайну? забудьте '\n'. пользуйтесь endl У вас буфер не сфлешился ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 08:45 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
blindedХотите я открою вам страшную тайну? забудьте '\n'. пользуйтесь endl У вас буфер не сфлешился хотя я вам открою страшную тайну? endl перегруженные оператор на '\n' ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 10:02 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Aklin blindedХотите я открою вам страшную тайну? забудьте '\n'. пользуйтесь endl У вас буфер не сфлешился хотя я вам открою страшную тайну? endl перегруженные оператор на '\n' А вот и нет это ends такой, а endl = ends + flush ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 10:10 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
grieg пишет: > Ой, и мне объясни тогда, почему нет печати из деструктора G. > Я не совсем вкурил. Я был не прав, не вызовется. Но на самом деле я и немного не то имел в виду. Что деструкторы будут вызываться (или не вызываться) безотносительно наличия стека обработки исключений где-либо. В общем, для всех полностью сконструированных подобъектов всегда будут вызваны деструкторы при выбрасывании исключения. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 12:04 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Aklin пишет: > хотя я вам открою страшную тайну? > endl перегруженные оператор на '\n' endl еще и вызывает flush() для потока. Поэтому << "\n" и << endl не эквивалентны. Posted via ActualForum NNTP Server 1.4 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 12:05 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
MasterZiv В общем, для всех полностью сконструированных подобъектов всегда будут вызваны деструкторы при выбрасывании исключения. Так почему в примере автора не вызывается? Если вставить в main блок try/catch(...), то вызывается. Топикстартеру. Содержательным вопросом случай, когда конструктор пробует захватить два ресурса и обламывается на втором. Деструктор не отрабатывает (поскольку объект так и не был создан) и первый ресурс "утекает". На этот случай есть правило: один конструктр -- один захват ресурса. Ну или можно думать о каких-то других методах. Например, захватывать память в auto_ptr, а потом уже передавать управление ей конструируемому объекту. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 14:56 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
grieg MasterZiv В общем, для всех полностью сконструированных подобъектов всегда будут вызваны деструкторы при выбрасывании исключения. Так почему в примере автора не вызывается? Если вставить в main блок try/catch(...), то вызывается. Да вызывается он, просто печать не происходит, в буфере застревает. grieg Топикстартеру. Содержательным вопросом случай, когда конструктор пробует захватить два ресурса и обламывается на втором. Деструктор не отрабатывает (поскольку объект так и не был создан) и первый ресурс "утекает". На этот случай есть правило: один конструктр -- один захват ресурса. Ну или можно думать о каких-то других методах. Например, захватывать память в auto_ptr, а потом уже передавать управление ей конструируемому объекту. Да у нас эта проблема возникает чуть ли не каждый месяц. если пошарить по форуму 10 ответов найдешь как правильно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 15:13 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
blinded Да вызывается он, просто печать не происходит, в буфере застревает. Увы, я проверял с cout<<endl -- не вызывается. Во всяком случае не выводится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 18:25 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
StepLgЕсть класс A, в котором генерируется исключение. Класс B наследуется от него. В обоих классах имеются данные, которые необходимо уничтожить при вызове этого исключения. Понятно, что это можно сделать какой-нибудь виртуальной функцией функцией. А что делать, если нужно вызвать деструктор? Прямой вызов в классе A деструктора this->~A() естественно не вызовет деструктор ~B(), как хотелось бы. Есть ли возможность это сделать? или вообще никак нельзя? Не понял. Вы хотите внутри класса A или B перехватить исключение из этого же класса и в нём же вызвать деструктор? Это круто, но невозможно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.04.2007, 19:34 |
|
||
|
наследование, исключения.
|
|||
|---|---|---|---|
|
#18+
Проведенные исследования показали, что реальная раскрутка стека (вызов деструкторов и т.д.) производится в момент обработки исключения. Не будет перехвата исключения - стек не раскрутится. Провеял и на gcc и VisualC++. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.04.2007, 11:12 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=34460866&tid=2029040]: |
0ms |
get settings: |
7ms |
get forum list: |
8ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
157ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
| others: | 252ms |
| total: | 500ms |

| 0 / 0 |
