
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.21] |
![]() |
|
Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Сообщ.
#16
,
|
|
|
Цитата D_KEY @ так, что не понятно, в каком состоянии находятся свойства класса. а для того, чтоб не городить код, проверяющий/утилизировавший свойства класса, проще исключения вообще не генерировать из конструктора. мое имхо. |
Сообщ.
#17
,
|
|
|
Цитата niXman @ так, что не понятно, в каком состоянии находятся свойства класса. После исключения??? Ни в каком. Объект будет разрушен, а память освобождена. Цитата а для того, чтоб не городить код, проверяющий/утилизировавший свойства класса... Так и не надо его городить. Цитата проще исключения вообще не генерировать из конструктора. мое имхо. Мне кажется, что оно основано на непонимании конструкторов, деструкторов и механизма исключений. |
Сообщ.
#18
,
|
|
|
Цитата niXman @ никогда в конструкторе не инициализирую то, что может бросить исключение. в худшем случае, инициализирую такие свойства в списке инициализаторов Если в классе применяется RAII, что должно быть, то пофигу (если не учитывать эффективность), а если нет - то поаккуратнее с "инициализирую такие свойства в списке инициализаторов" ![]() ![]() class A { public: A() : ..., p(new int) {} // небезопасно, в отличие от //A() : ... { p = new int; } - "безопасно", пока не будет меняться тело конструктора так, что станет возможно исключение после строчки p = new int; ~A() { delete p; } ... int* p; .... } |
Сообщ.
#19
,
|
|
|
Цитата Hryak @ ![]() ![]() A() : ..., p(new int) {} // небезопасно Почему? По-моему, безопасно, если Цитата Hryak @ ![]() ![]() int* p; описано последним полем, инициализация которого может кинуть исключение, и тело конструктора не бросает исключений (как, собственно, у вас и есть). |
Сообщ.
#20
,
|
|
|
MyNameIsIgor
А при модификации такого класса через год ты будешь помнить обо всех этих "если"?) |
Сообщ.
#21
,
|
|
|
Цитата LuckLess @ А при модификации такого класса через год ты будешь помнить обо всех этих "если"?) Это уже другой вопрос. Если вы читали топик, то я только "за" применения RAII. Понятно, что смартпоинтер будет лучше голого указателя. |
Сообщ.
#22
,
|
|
|
Цитата MyNameIsIgor @ безопасно, если Цитата Hryak @ ![]() ![]() int* p; описано последним полем, инициализация которого может кинуть исключение Кто сказал, что последним? Я же не зря многоточия поставил в описании класса. Одно дело - когда пишешь тело конструктора и четко видишь, что в нем, и только это влияет на безопасность кода, и другое - когда еще нужно держать в голове последовательность определения полей в классе... P.S. Мой пост был исключительно о том, что не всегда инициализация мемберов в initialization list лучше присвоения в теле конструктора. |
Сообщ.
#23
,
|
|
|
в общем, понятно, никто не против try-catch в конструкторе.
хотя, не могу вспомнить, чтоб в реальных проектах не новичков, встречал такое. вопрос закрыт. Добавлено Цитата Hryak @ Мой пост был исключительно о том, что не всегда инициализация мемберов в initialization list лучше присвоения в теле конструктора. буду знать. |
Сообщ.
#24
,
|
|
|
Цитата niXman @ хотя, не могу вспомнить, чтоб в реальных проектах не новичков, встречал такое Обычно тяжеловесные операции лучше не в конструкторе делать, а в методе вроде Init(). Тогда получается двухфазное создание экземпляров: 1) инстанс аллоцирован, но при попытке использования должны кидаться исключения/осетры/что-там-по-правилам-проекта. 2) инстанс инициирован, можно пользовать. Плюс такого подхода может быть в том, что шаг 1 исполняется очень быстро. Эдакий lazy load. Также, если два разных класса используют сервисы друг друга (например, подпиской через абстрактный интерфейс), то возникает парадокс курицы и яйца - непонятно, кого делать первым. А так - инстанциируем в любом порядке, и в init-коде даем ссылки друг на друга. |
Сообщ.
#25
,
|
|
|
Цитата Mr.Delphist @ Обычно тяжеловесные операции лучше не в конструкторе делать, а в методе вроде Init(). Тогда получается двухфазное создание экземпляров: 1) инстанс аллоцирован, но при попытке использования должны кидаться исключения/осетры/что-там-по-правилам-проекта. 2) инстанс инициирован, можно пользовать. Зачем так делать? Это лишняя путаница в коде. Цитата Смысл?Плюс такого подхода может быть в том, что шаг 1 исполняется очень быстро. Эдакий lazy load. Цитата Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь.Также, если два разных класса используют сервисы друг друга (например, подпиской через абстрактный интерфейс), то возникает парадокс курицы и яйца - непонятно, кого делать первым. А так - инстанциируем в любом порядке, и в init-коде даем ссылки друг на друга. А можно пример такой ситуации? |
Сообщ.
#26
,
|
|
|
Цитата D_KEY @ Зачем так делать? Это лишняя путаница в коде. Например, оптимизация с точки зрения performance. Особенно на legacy-коде, когда взять и переписать по уму - без вариантов, ибо релиз на носу. Или когда физических ресурсов доступно в разы меньше, чем логических оберток вокруг них (эдаких смарт-хэндлов) - тогда инициализация аттачит инстанс с физическим ресурсом, а деинициализация - детачит. Цитата D_KEY @ Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь. А можно пример такой ситуации? Например, когда есть две коллекции разных сущностей, но каждая из них заинтересована в нотификации об изменениях в другой (дабы ре-валидировать себя заново, допустим). Тут в конструкторах создаем, а в init() - оформляем подписки. |
Сообщ.
#27
,
|
|
|
Цитата Mr.Delphist @ Цитата D_KEY @ Зачем так делать? Это лишняя путаница в коде. Например, оптимизация с точки зрения performance. Особенно на legacy-коде, когда взять и переписать по уму - без вариантов, ибо релиз на носу. Так как это помогает с точки зрения performance? Цитата Или когда физических ресурсов доступно в разы меньше, чем логических оберток вокруг них (эдаких смарт-хэндлов) - тогда инициализация аттачит инстанс с физическим ресурсом, а деинициализация - детачит. Как это связано с методами init()? То есть вы предлагаете, чтобы код, использующий такие объекты, задумывался о реализации и сам вызывал методы инициализации/деинициализации? Не лучше ли инкапсулировать это поведение так, чтобы внешний код работал с такими объектами, как с обычными? Цитата А может нужен просто метод для подписки?Цитата D_KEY @ Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь. А можно пример такой ситуации? Например, когда есть две коллекции разных сущностей, но каждая из них заинтересована в нотификации об изменениях в другой (дабы ре-валидировать себя заново, допустим). Тут в конструкторах создаем, а в init() - оформляем подписки. Init - дурацкое название, ибо неясно, что за ним скрывается. |