На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Закрыто archimed7592 11-03-2008: Лимит страниц. Продолжаем Delphi vs C++

Страницы: (117) « Первая ... 96 97 [98] 99 100 ...  116 117  ( Перейти к последнему сообщению )  
> Delphi vs C++ , Часть 1
    Цитата --Ins-- @
    Romkin, хорошо, если ты понял, о чем я. Вернемся к примеру
    T1 = class(TObject)
    procedure Test(I: Integer); virtual;
    end;
    T2 = class(T1)
    procedure Test(S: string); overload; virtual;
    procedure Test(E: Extended); overload; virtual;
    end;

    где метод скрывается действительно. И среда об этом честно предупреждает. У меня два вопроса.
    1. Почему он скрывается, если в справке явно сказано:
    Цитата
    A method can be redeclared using the overload directive. In this case, if the redeclared method has a different parameter signature from its ancestor, it overloads the inherited method without hiding it. Calling the method in a descendant class activates whichever implementation matches the parameters in the call.

    2. Почему если объявить метод с параметром E, не как Extended, а TObject, ничего не скрывается? В чем принципиальное отличие?

    Ты говоришь о случае, когда переменная сразу объявлена потомком. Тогда в случае extended компилятор просто колдобится из-за невозможности решить, хочешь ли ты вызвать метод предка или тот, что есть, поскольку подходят оба. Он разравается между двумя приоритетами: вроде у типа, который ты объявил (потомок, с которым работаешь), есть метод, который нужно вызвать, но у предка есть метод с более подходящим типом параметра... И все потому, что целое неявно можно преобразовать к extended.
    В случае TObject решение однозначно. Также решение однозначно, если ты перекроешь явно в потомке метод предка - вызовется метод потомка.
      Romkin, ладно, фиг с ним... Я просто однажды наткнулся на "фичу" связанную с overload, и теперь с ними осторожен. ;)

      Цитата
      Когда ты вызываешь метод для конкретного производного класса, никакой виртуальности нет - все уже известно на этапе компиляции.


      Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм.
        Цитата --Ins-- @
        Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм.

        Да. Но смещение в VMT прописывается на этапе компиляции. В твоем случае компилятор не может решить, какое смещение дать.
          Цитата
          Да. Но смещение в VMT прописывается на этапе компиляции.


          Ясный пень. Это не к тебе коммент, а к Flex Ferrum. Насчет варнинга - если есть желание, можно продолжить в привате, здесь как-то это странновато...
            Цитата --Ins-- @
            Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм.


            В плюсах есть разница. Если ты обращаешься к методу по т. н. неквалифицированному имени, а слева у тебя стоит указатель или ссылка на объект - тогда вызов будет виртуальным (если метод виртуальный). В остальных случаях вызов будет прямым. Т. е.:
            ExpandedWrap disabled
              class Base
              {
              public:
                 virtual void foo();
              };
               
              class Derived
              {
              public:
                 void foo();
              };
               
              //...
              Base b1;
              Derived d1;
              Base& b2 = b1;
              Base& b3 = d1;
              Derived& d2 = d1;
               
               
              b1.foo(); // прямой вызов
              b2.foo(); // виртуальный вызов, вызовется Base::foo()
              b3.foo(); // виртуальный вызов, вызовется Derived::foo()
              d1.foo(); // прямой вызов
              d2.foo(); // виртуальный вызов
              d2.Base::foo(); // прямой вызов
              //...
              Цитата
              В плюсах есть разница. Если ты обращаешься к методу по т. н. неквалифицированному имени, а слева у тебя стоит указатель или ссылка на объект - тогда вызов будет виртуальным (если метод виртуальный). В остальных случаях вызов будет прямым.


              Ну и глупо значит сделано. Так как вызов в коде "не своей" реализации виртуального метода говорит о неправильно спроектированной архитектуре.
                Цитата --Ins-- @
                Ну и глупо значит сделано. Так как вызов в коде "не своей" реализации виртуального метода говорит о неправильно спроектированной архитектуре.

                Ну почему же? Становится вполне допустимым такой код:
                ExpandedWrap disabled
                  class Derived : public Base
                  {
                  public:
                     void foo()
                     {
                         Base::foo(); // прямой вызов реализации метода foo из базового класса
                         // реализация метода
                     }
                  };
                   
                  // ...
                  Derived d;
                  d.foo(); // зачем здесь виртуализация вызова, если тип объекта доподлинно известен в точке вызова, и не может быть никаким другим?
                  // ...
                  Flex Ferrum, правильно ли я понимаю, что для потомка с перекрытым виртуальным методом, есть возможность вызова реализации виртуального метода предка(ов)? Если да, то эта возможность провоцирует к написанию плохого объектного кода. Это позволяет обойти объектно-ориентированные принципы, в частности - полиморфизм, заменив их своими "поделками".
                    Цитата --Ins-- @
                    Flex Ferrum, правильно ли я понимаю, что для потомка с перекрытым виртуальным методом, есть возможность вызова реализации виртуального метода предка(ов)? Если да, то эта возможность провоцирует к написанию плохого объектного кода. Это позволяет обойти объектно-ориентированные принципы, в частности - полиморфизм, заменив их своими "поделками".

                    Правильно ли я понимаю, что острая заточка ножа позволят откромсать себе полпальца, а значит провоцирует на членовредительство? :) Аналогия прозрачна? :) Будем пользоваться тупыми ножами? :whistle:

                    Добавлено
                    А если серьезно, такие вещи можно сделать только намеренно (явно квалифицировав имя метода). "Случайно" написать плохой код у тебя не получится. А намеренно - ты это сделаешь и без таких возможностей. :)
                      Flex Ferrum

                      Угу. Знаете, как в одном анектоде... "Его последними словами были "Не бойся, дорогая, я уже сто раз так делал!"". :D Знаете, когда все разрешено - это не правильно. Язык Pascal хорош тем, что заставляет разработчика тщательно продумать архитектуру, прежде чем приступить к реализации. А в C++ - сначала пишем, потом думаем как выкрутиться. И ведь выкрутимся, потому что все разрешено. Меня искренне радует, что в современных объектно-ориентированных языках учтены многие недочеты C++. У меня складываеься четкое впечатление, будто бы C++ придумывали по принципу "чем больше - тем лучше", не стараясь соблюсти какую-либо логику. И плевать они хотели на стандарты императивных языков и ООП. :yes-sad:
                      Знаете почему в C/C++ чувствительный к регистру синтаксис?

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


                      Лично я, намерянно никогда такого не делал и даже никогда мне такого не требовалось. Бо для меня это дикость (такая же, как и множественное наследование реализаций.). В грамотно спроектированной системе такого быть не должно. :wacko:
                        Цитата --Ins-- @
                        Угу. Знаете, как в одном анектоде... "Его последними словами были "Не бойся, дорогая, я уже сто раз так делал!"". :D Знаете, когда все разрешено - это не правильно. Язык Pascal хорош тем, что заставляет разработчика тщательно продумать архитектуру, прежде чем приступить к реализации. А в C++ - сначала пишем, потом думаем как выкрутиться. И ведь выкрутимся, потому что все разрешено. Меня искренне радует, что в современных объектно-ориентированных языках учтены многие недочеты C++. У меня складываеься четкое впечатление, будто бы C++ придумывали по принципу "чем больше - тем лучше", не стараясь соблюсти какую-либо логику. И плевать они хотели на стандарты императивных языков и ООП. :yes-sad:
                        Знаете почему в C/C++ чувствительный к регистру синтаксис?

                        Т. е., продолжая аналогию, всех мужиков, прошу прощения, надо кастрировать, т. к. они своим хозяйством чего доброго и изнасиловать могут. Ну ведь могут же? :) Ножницы должны выпускаться полузаточенными и обязательно с тупыми концами - а то ведь глаз выколоть можно, порезаться и все такое. Автомобили - с физическим (на уровне коробке передач и мощностью двигателя) ограничением скорости не больше 20 км/ч, а то разгонится один такой, и собьет кого-нибудь. И вообще, надо всем срочно залезать в герметичные шары и молча ползти на кладбище, а то ведь мало ли чего... :) Голова человеку дана чтобы думать - разве не так?
                          Цитата
                          Голова человеку дана чтобы думать - разве не так?


                          Так. Только такая возможность его провоцирует не думать. Вы лучше объясните, какие мы преимущества от этой возможности получаем, какие недостатки - я сам вижу :)
                            Цитата --Ins-- @
                            Только такая возможность его провоцирует не думать. Вы лучше объясните, какие мы преимущества от этой возможности получаем, какие недостатки - я сам вижу :)

                            Это каким же это образом она его провоцирует?
                              Все ваши аналогии кривоваты на мой взгляд :) Без "хозяйства" мужчина - не мужчина, ножницы предназначены для резки, а значит должны быть острыми. В противовес - без данной "фичи" все принципы ООП сохраняются. А на этих принципах строится любая эффективная система. Мы же вводим некую возможность, которая в принципе не нужна, но пусть будет, бо не у кого такой нет. И ничего хорошего она не дает, только потенциальные проблемы. Никак не сравнивается с мужским "хозяйством" или заточенностью ножниц :)

                              Добавлено
                              Цитата
                              Это каким же это образом она его провоцирует?


                              Я же говорил, что возможность вызова виртуального метода предка, который в данном классе был перекрыт, противоречит принципам объектно-ориентированного проектирования. Но так как это возможно, программист так и поступит (это же гораздо проще), вместо того, чтобы изначально правильно спроектировать систему, в которой такой необходимости нет.
                                Цитата --Ins-- @
                                Но так как это возможно, программист так и поступит (это же гораздо проще), вместо того, чтобы изначально правильно спроектировать систему, в которой такой необходимости нет.

                                В том то и дело, что не проще. Для этого вместо
                                Derived* b;
                                b->SomeMethod()

                                надо написать:
                                Base* b;
                                b->Base::SomeMethod();

                                Как видишь, телодвижений несколько, гм, больше. По этому и говорю - "случайно" воспользоваться этой возможностью равносильно тому, что ты "случайно" откромсаешь себе ножом полпальца. И второй момент - совсем новички о такой возможности просто не знают, т. к. в соответствующей литературе такая форма вызова метода не описывается.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (117) « Первая ... 96 97 [98] 99 100 ...  116 117
                                Закрыто archimed7592 11-03-2008: Лимит страниц. Продолжаем Delphi vs C++



                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1106 ]   [ 15 queries used ]   [ Generated: 26.07.25, 11:49 GMT ]