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

        При чём тут один параметр? Используется для того, чтобы конструктор задавали явно.
          А как можно неявно задать конструктор с более чем один параметром?
          Сообщение отредактировано: Крон -
            Цитата Крон @
            А как можно неявно задать конструктор с более чем один параметром?

            ExpandedWrap disabled
              class A
              {
                A(int first, int second);
                ~A();
              };
              Цитата Алкаш @
              Используется для того, чтобы конструктор задавали явно.

              Ок, а что такое по твоему "задать конструктор"? :)


              DelphiLexx,
              ExpandedWrap disabled
                struct A
                {
                    A(int) { }
                };
                struct B
                {
                    explicit B(int) { }
                };
                 
                int main()
                {
                    A a1(5); // ok
                    B b1(5); // ok
                    A a2 = 10; // ok
                    B b2 = 10; // error  <<<==========================
                }
                Цитата archimed7592 @
                Ок, а что такое по твоему "задать конструктор"? :)

                Цитата archimed7592 @
                B b1(5); // ok
                  Цитата Алкаш @
                  Цитата Крон @
                  Используется в конструкторах с одним парамтером.

                  При чём тут один параметр? Используется для того, чтобы конструктор задавали явно.


                  Интересно а для чего использовать тогда explicit c конструктором который имеет более чем один параметр? Я просто не вижу смысла потому что приведение и так неявное невозможно. А archimed7592 уже ответил на вопрос полностъю я считаю.
                  Сообщение отредактировано: Craft -
                    Цитата Craft @
                    Интересно а для чего использовать тогда explicit c конструктором который имеет более чем один параметр?

                    ExpandedWrap disabled
                      struct S {
                       /*explicit*/ S(int, int = 0) {}
                      };
                       
                      int main() {
                       S s = 10;
                      }

                    раскомментируй explicit
                      ExpandedWrap disabled
                        class Foo
                        {
                        public:
                              Foo(const std::string & sString, bool Flag = true);
                              Foo(bool Flag);
                        ...
                        };


                      Вот пример такой класс, а теперь прикол :
                      ExpandedWrap disabled
                        Foo("foo");

                      Вызывется 2-ой конструктор, а не первый. Понятно что есть небольшая ошибка, что ведь нужен обьект типа string, а я передаю const char * - это простая ошибка которая может возникнуть в процессе кодирования, когда нету autocomplete и программист уже устал.
                      Если сделать оба конструктора explicit, такой ошибки не будет и компилятор предупредит об этой ошибки с неявным преобразованием. На эту ошибку наткнулся в реальном коммерческом проекте.
                      Вывод : всегда делать конструкторы explicit, если у него есть параметры.
                      Сообщение отредактировано: Cechmanek -
                        Alek86 Я не имел ввиду что конструктор принимает значения по умолчанию. Так можна и 10 аргументов инициализировать по умолчанию. Ты же инициализуеш неявно только первый аргумент, а остальныи присваиваеш значение по умолчанию. Я знаю как работает explicit и для чего он нужен.
                        Допустим без explicit у тебя конструктор автоматически определил бы преобразования из int в твой клас S, ну создаст он стек на 10 елементов. Да не спорю это не то что мы ожидаем. Но первая переменная у тебя всё равно получит значение 10. Так работает неявное преобразование. Большой минус только что стек сильно увеличивается. Это неправильный стиль я не спорю. Но чтоб считать это такой уж ошибкой я не вижу смысла. Программист должен знать что он делает в первую очередь. Пусть хоть на миллион элементов неявно инициализацию использует. Лиш бы ему памъяти хватило чтоб небыло переполнения. Просто насколько мне не изменяет памъять то у windows под кучю выделяется 1Мб так что если не жалко израсходованой памъяти то можна такой метод использовать. Я никогда не видел что ктото использовал неявное преобразование на подобие этого
                        ExpandedWrap disabled
                          S s = 10;
                        кроме тестовых каких нибуть примеров. Начинающий программист в основном не использует explicit, а опытный программист просто напросто никогда не напишет такой код который я написал више. Так что особого кризиса как такового и нету ;)

                        P.S. Если чесно, то я не подумал, когда писал ответ, про возможность передачи значения по умолчанию.

                        ExpandedWrap disabled
                          Cechmanek
                        Неплохой пример. Но у тебя ошибка у примере. Даже если ты напишеш два конструктора как explicit через такую запись ти не увидиш ошибку компиляции.
                        ExpandedWrap disabled
                          Foo("foo");

                        Разве что через такую
                        ExpandedWrap disabled
                          Foo p = "foo";
                        а то что ты описал это явное преобразование. И никакой ошибки ты не получиш даже если конструктор объявлен как explicit. Посмотри на пример archimed7592
                        Цитата
                        B b1(5); // ok
                        Сообщение отредактировано: Craft -
                          Цитата Cechmanek @
                          Вызывется 2-ой конструктор, а не первый.

                          Это потому что последовательность преобразований из массива char в bool - стандартная, а в std::string - пользовательская. При разрешении перегрузки предпочтение отдаётся последовательности стандартных преобразований.

                          Цитата Cechmanek @
                          Если сделать оба конструктора explicit

                          то в этом плане ничего не изменится.

                          Цитата Cechmanek @
                          Вывод : всегда делать конструкторы explicit, если у него есть параметры.

                          Плохой вывод.
                          Сообщение отредактировано: Dantes -
                            Один из способов из способов избежать создания временных объектов это по возможности использовать объявления конструкторов как
                            ExpandedWrap disabled
                              explicit
                            . :)
                            Вот и все. 8-)
                            Сообщение отредактировано: vovan01 -
                              Цитата Craft @
                              Начинающий программист в основном не использует explicit, а опытный программист просто напросто никогда не напишет такой код который я написал више.

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

                              и потому же рекомендуют пореже писать кастомных операторов преобразования

                              насчет правила "ставить explicit всегда и везде" не согласен, но только потому что не обжигался на этом "в реале" :)
                              я ставлю его только тогда, когда "чувствую" что тут его лучше поставить
                              Сообщение отредактировано: Alek86 -
                                Craft и Archimed раскрыли тему полностью :yes:

                                Цитата
                                Один из способов из способов избежать создания временных объектов это по возможности использовать объявления конструкторов как

                                временные объекты здесь вообще не при чём.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0721 ]   [ 16 queries used ]   [ Generated: 3.05.24, 19:56 GMT ]