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

        Добавлено
        Цитата JoeUser @
        А по-моему лучше кидать исключение.
        Куда? В ветвь оконной процедуры? И как потом продолжить нормальную работу гуя? Ладно, не велика сложность. Для одного раза. Но ловить исклюкаку придётся по всей приладе, а это уже повод для максимального упрощения. Трай им не страдает.
        Сообщение отредактировано: Ирокез -
          Цитата Ирокез @
          Куда? В ветвь оконной процедуры?

          Кидают не куда, а где. А "куда" - это где обрабатывают.
          Простой пример, понятный и удобный;
          ExpandedWrap disabled
            #include <iostream>
            using namespace std;
             
            class MyArray10 {
              public:
                MyArray10() : a{'0','1','2','3','4','5','6','7','8','9'} {};
                char &operator[](size_t idx) {
                  if (idx>9) throw std::out_of_range("MyArray10");
                  return a[idx];
                }
              private:  
                char a[10];
            };
             
            int main() {
              MyArray10 Arr;
              try {
                std::cout << std::hex << Arr[1] << std::endl;
                std::cout << std::hex << Arr[10] << std::endl;
              } catch (std::out_of_range &e) {
                std::cout << "Выход за границы массива в: " << e.what() << std::endl;
              } catch (...) {
                std::cout << "Произошла неведомая хрень" << std::endl;
              }
              return 0;
            }


          Добавлено
          Цитата Ирокез @
          И как потом продолжить нормальную работу гуя?

          Не сложнее, если ты будешь отлавливать предварительно условными операторами.
          Сообщение отредактировано: JoeUser -
            Хотелось бы без неё, пусть даже переусложнив одно место. А если уж делать через неё, то какую именно исклюкаку принято бросать? Я попробовал
            ExpandedWrap disabled
              throw *this
            и поймать исклюкаку с параметром ссылка на объект-массив, софтина упала при закрытии.

            Добавлено
            Цитата JoeUser @
            Кидают не куда
            Ну где – это в операторе.
              Цитата Ирокез @
              то какую именно исклюкаку принято бросать

              Я в примере ее привел - std::out_of_range

              Добавлено
              Если хочется еще и this знать - нужно реализовать свой класс исключения, наследовавшись от std::out_of_range.

              Добавлено
              Хотя ... можно и адрес передавать при выбросе исключения:

              ExpandedWrap disabled
                #include <iostream>
                using namespace std;
                 
                template<typename S,typename D>
                D type_cast(S s) {
                  union Tmp {
                    S src;
                    D dst;
                  } T;
                  T.src = s;
                  return T.dst;
                }
                 
                class MyArray10 {
                  public:
                    MyArray10() : a{'0','1','2','3','4','5','6','7','8','9'} {};
                    char &operator[](size_t idx) {
                      if (idx>9) throw std::out_of_range(type_cast<MyArray10*,char*>(this));
                      return a[idx];
                    }
                  private:
                    char a[10];
                };
                 
                int main() {
                  MyArray10 Arr;
                  try {
                    std::cout << std::hex << Arr[1] << std::endl;
                    std::cout << std::hex << Arr[10] << std::endl;
                  } catch (std::out_of_range &e) {
                    std::cout << "Выход за границы массива в: " << std::hex << static_cast <const void *> (e.what()) << std::endl;
                  } catch (...) {
                    std::cout << "Произошла неведомая хрень" << std::endl;
                  }
                  return 0;
                }
                Цитата JoeUser @
                Хотя ... можно и адрес передавать при выбросе исключения:
                Что я с ним делать буду? Объект хоть тип имеет, по нему можно понять, оператор-член какого класса бросал. А адрес я куда приткну?
                Сообщение отредактировано: Ирокез -
                  Цитата Ирокез @
                  Что я с ним делать буду?

                  Без понятия. Это был ответ на ваш вопрос #5.
                  Вы в исключении передавали this и у вас программа падала. Я показал как передать, чтобы не падала, и как это адрес в обработчике достать.
                  Хотите более детальной обработки, творите. Default решений тут нет.

                  Цитата Ирокез @
                  Объект хоть тип имеет, по нему можно понять, оператор-член какого класса бросал

                  Откройте для себя RTTI, хотя бы почитайте про std::type_info.
                    Цитата JoeUser @
                    Вы в исключении передавали this
                    Учитесь читать. Я передал ссылку на this.

                    Добавлено
                    Цитата JoeUser @
                    Откройте для себя RTTI,
                    Вот только она разбирает фактические типы объектов, а не адреса кода.
                      Цитата Ирокез @
                      Учитесь читать. Я передал ссылку на this.

                      И результат - падение программы. Я это читал.

                      Добавлено
                      Цитата Ирокез @
                      Объект хоть тип имеет, по нему можно понять, оператор-член какого класса бросал

                      Цитата Ирокез @
                      Вот только она разбирает фактические типы объектов, а не адреса кода.

                      Сначала же надо было знать тип?! Или, по мере обсуждения, цели меняются? :lol:
                        Цитата JoeUser @
                        И результат - падение программы. Я это читал.
                        Не читал, а выхватил.

                        Добавлено
                        Цитата JoeUser @
                        Сначала же надо было знать тип?!
                        Да. Но Вы-то предлагали адрес операции, на которой исклюкака брошена.

                        Добавлено
                        Цитата JoeUser @
                        Или, по мере обсуждения, цели меняются? :lol:
                        Не цели, а средства. Цель – узнать, чем вызвана исклюкака.
                          В последнем моем варианте в исключении прилетает адрес экземпляра класса, в операторе которого произошло исключение. Тип этого экземпляра класса узнать можно. Если нужно еще что-то, это нужно реализовывать самостоятельно. В отличии от языков с динамической типизацией, в С++ из подобного только RTII со своими фишками. Но нет преграды патриотам.

                          Добавлено
                          Цитата Ирокез @
                          Вы-то предлагали адрес операции, на которой исклюкака брошена

                          Адрес точно операции? :wacko:
                            Цитата JoeUser @
                            Адрес точно операции?
                            А чего? Места жительства Меркель?

                            Добавлено
                            Цитата JoeUser @
                            В последнем моем варианте в исключении прилетает адрес экземпляра класса, в операторе которого произошло исключение. Тип этого экземпляра класса узнать можно. Если нужно еще что-то, это нужно реализовывать самостоятельно.
                            Чтоб по адресу узнать фактический тип, его надо запихать в указатель на базовый класс. А что это за класс?

                            Добавлено
                            Цитата JoeUser @
                            В отличии от языков с динамической типизацией,
                            В c++ размещаемые в куче экзмлпяры полиморфных классов получают фактические типы вполне динамически.
                            Сообщение отредактировано: Ирокез -
                              Цитата JoeUser @
                              А по-моему лучше кидать исключение.
                              Лучше? Только исключение. Никаких вариантов.

                              Добавлено
                              Цитата Ирокез @
                              Что я с ним делать буду? Объект хоть тип имеет, по нему можно понять, оператор-член какого класса бросал. А адрес я куда приткну?
                              Нагрузить экземпляр исключения любой информацией никто не мешает. Какая там будет нужна информация, кроме автора кода, знать некому, так что "пилите Шура, пилите"©, компилятор сам по наитию этого не сделает
                                Цитата Ирокез @
                                Чтоб по адресу узнать фактический тип, его надо запихать в указатель на базовый класс. А что это за класс?

                                Ну я же давал ссылку на доки. Что и так почитать лень? :facepalm:
                                Хотите узнать название класса? В доке и пример есть:
                                ExpandedWrap disabled
                                  #include <iostream>
                                  #include <typeinfo>
                                   
                                  struct Base { virtual ~Base() = default; };
                                  struct Derived : Base {};
                                   
                                  int main() {
                                      Base b1;
                                      Derived d1;
                                   
                                      const Base *pb = &b1;
                                      std::cout << typeid(*pb).name() << '\n';
                                      pb = &d1;
                                      std::cout << typeid(*pb).name() << '\n';
                                  }


                                Добавлено
                                Цитата Qraizer @
                                Лучше? Только исключение. Никаких вариантов.

                                Да, тамошний пример от интуристов, что я приводил, в плане работы с ошибками - хрень. Согласен.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0557 ]   [ 17 queries used ]   [ Generated: 16.04.24, 06:07 GMT ]