На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> try-catch в конструкторе? оО
    Цитата D_KEY @
    Цитата niXman @
    Цитата D_KEY @
    А вот это уже непонятно и мало связано с описанным случаем.

    я никогда не допускаю в коде, ситуацию, двусмысленную/неопределенную. сейчас ссылку поищу...

    А как с помощью исключений из конструктора можно допустить двусмысленную ситуацию?

    так, что не понятно, в каком состоянии находятся свойства класса.
    а для того, чтоб не городить код, проверяющий/утилизировавший свойства класса, проще исключения вообще не генерировать из конструктора. мое имхо.
      Цитата niXman @
      так, что не понятно, в каком состоянии находятся свойства класса.

      После исключения??? Ни в каком. Объект будет разрушен, а память освобождена.

      Цитата
      а для того, чтоб не городить код, проверяющий/утилизировавший свойства класса...

      Так и не надо его городить.

      Цитата
      проще исключения вообще не генерировать из конструктора. мое имхо.

      Мне кажется, что оно основано на непонимании конструкторов, деструкторов и механизма исключений.
        Цитата niXman @
        никогда в конструкторе не инициализирую то, что может бросить исключение. в худшем случае, инициализирую такие свойства в списке инициализаторов

        Если в классе применяется RAII, что должно быть, то пофигу (если не учитывать эффективность), а если нет - то поаккуратнее с "инициализирую такие свойства в списке инициализаторов"
        ExpandedWrap disabled
          class A
          {
          public:
            A() : ..., p(new int) {} // небезопасно, в отличие от
            //A() : ... { p = new int; } - "безопасно", пока не будет меняться тело конструктора так, что станет возможно исключение после строчки p = new int;
            ~A() { delete p; }
          ...
            int* p;
          ....
          }
          Цитата Hryak @
          ExpandedWrap disabled
            A() : ..., p(new int) {} // небезопасно

          Почему? По-моему, безопасно, если
          Цитата Hryak @
          ExpandedWrap disabled
            int* p;

          описано последним полем, инициализация которого может кинуть исключение, и тело конструктора не бросает исключений (как, собственно, у вас и есть).
          Сообщение отредактировано: MyNameIsIgor -
            MyNameIsIgor
            А при модификации такого класса через год ты будешь помнить обо всех этих "если"?)
              Цитата LuckLess @
              А при модификации такого класса через год ты будешь помнить обо всех этих "если"?)

              Это уже другой вопрос. Если вы читали топик, то я только "за" применения RAII. Понятно, что смартпоинтер будет лучше голого указателя.
                Цитата MyNameIsIgor @
                безопасно, если
                Цитата Hryak @
                ExpandedWrap disabled
                  int* p;

                описано последним полем, инициализация которого может кинуть исключение

                Кто сказал, что последним? Я же не зря многоточия поставил в описании класса.
                Одно дело - когда пишешь тело конструктора и четко видишь, что в нем, и только это влияет на безопасность кода, и другое - когда еще нужно держать в голове последовательность определения полей в классе...

                P.S. Мой пост был исключительно о том, что не всегда инициализация мемберов в initialization list лучше присвоения в теле конструктора.
                  в общем, понятно, никто не против try-catch в конструкторе.
                  хотя, не могу вспомнить, чтоб в реальных проектах не новичков, встречал такое.
                  вопрос закрыт.

                  Добавлено
                  Цитата Hryak @
                  Мой пост был исключительно о том, что не всегда инициализация мемберов в initialization list лучше присвоения в теле конструктора.

                  буду знать.
                    Цитата niXman @
                    хотя, не могу вспомнить, чтоб в реальных проектах не новичков, встречал такое


                    Обычно тяжеловесные операции лучше не в конструкторе делать, а в методе вроде Init(). Тогда получается двухфазное создание экземпляров:
                    1) инстанс аллоцирован, но при попытке использования должны кидаться исключения/осетры/что-там-по-правилам-проекта.
                    2) инстанс инициирован, можно пользовать.

                    Плюс такого подхода может быть в том, что шаг 1 исполняется очень быстро. Эдакий lazy load.
                    Также, если два разных класса используют сервисы друг друга (например, подпиской через абстрактный интерфейс), то возникает парадокс курицы и яйца - непонятно, кого делать первым. А так - инстанциируем в любом порядке, и в init-коде даем ссылки друг на друга.
                      Цитата Mr.Delphist @
                      Обычно тяжеловесные операции лучше не в конструкторе делать, а в методе вроде Init(). Тогда получается двухфазное создание экземпляров:
                      1) инстанс аллоцирован, но при попытке использования должны кидаться исключения/осетры/что-там-по-правилам-проекта.
                      2) инстанс инициирован, можно пользовать.

                      Зачем так делать? Это лишняя путаница в коде.

                      Цитата
                      Плюс такого подхода может быть в том, что шаг 1 исполняется очень быстро. Эдакий lazy load.
                      Смысл?

                      Цитата
                      Также, если два разных класса используют сервисы друг друга (например, подпиской через абстрактный интерфейс), то возникает парадокс курицы и яйца - непонятно, кого делать первым. А так - инстанциируем в любом порядке, и в init-коде даем ссылки друг на друга.
                      Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь.
                      А можно пример такой ситуации?
                        Цитата D_KEY @
                        Зачем так делать? Это лишняя путаница в коде.

                        Например, оптимизация с точки зрения performance. Особенно на legacy-коде, когда взять и переписать по уму - без вариантов, ибо релиз на носу.
                        Или когда физических ресурсов доступно в разы меньше, чем логических оберток вокруг них (эдаких смарт-хэндлов) - тогда инициализация аттачит инстанс с физическим ресурсом, а деинициализация - детачит.

                        Цитата D_KEY @
                        Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь.
                        А можно пример такой ситуации?

                        Например, когда есть две коллекции разных сущностей, но каждая из них заинтересована в нотификации об изменениях в другой (дабы ре-валидировать себя заново, допустим). Тут в конструкторах создаем, а в init() - оформляем подписки.
                          Цитата Mr.Delphist @
                          Цитата D_KEY @
                          Зачем так делать? Это лишняя путаница в коде.

                          Например, оптимизация с точки зрения performance. Особенно на legacy-коде, когда взять и переписать по уму - без вариантов, ибо релиз на носу.

                          Так как это помогает с точки зрения performance?

                          Цитата
                          Или когда физических ресурсов доступно в разы меньше, чем логических оберток вокруг них (эдаких смарт-хэндлов) - тогда инициализация аттачит инстанс с физическим ресурсом, а деинициализация - детачит.

                          Как это связано с методами init()? То есть вы предлагаете, чтобы код, использующий такие объекты, задумывался о реализации и сам вызывал методы инициализации/деинициализации?
                          Не лучше ли инкапсулировать это поведение так, чтобы внешний код работал с такими объектами, как с обычными?

                          Цитата
                          Цитата D_KEY @
                          Скорее всего тут ошибка уровня выше, хотя может я ошибаюсь.
                          А можно пример такой ситуации?

                          Например, когда есть две коллекции разных сущностей, но каждая из них заинтересована в нотификации об изменениях в другой (дабы ре-валидировать себя заново, допустим). Тут в конструкторах создаем, а в init() - оформляем подписки.
                          А может нужен просто метод для подписки?
                          Init - дурацкое название, ибо неясно, что за ним скрывается.
                          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0648 ]   [ 15 queries used ]   [ Generated: 17.06.25, 05:03 GMT ]