
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.188] |
![]() |
|
Страницы: (117) « Первая ... 96 97 [98] 99 100 ... 116 117 ( Перейти к последнему сообщению ) |
Сообщ.
#1456
,
|
|
|
Цитата --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 решение однозначно. Также решение однозначно, если ты перекроешь явно в потомке метод предка - вызовется метод потомка. |
Сообщ.
#1457
,
|
|
|
Romkin, ладно, фиг с ним... Я просто однажды наткнулся на "фичу" связанную с overload, и теперь с ними осторожен.
![]() Цитата Когда ты вызываешь метод для конкретного производного класса, никакой виртуальности нет - все уже известно на этапе компиляции. Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм. |
Сообщ.
#1458
,
|
|
|
Цитата --Ins-- @ Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм. Да. Но смещение в VMT прописывается на этапе компиляции. В твоем случае компилятор не может решить, какое смещение дать. |
Сообщ.
#1459
,
|
|
|
Цитата Да. Но смещение в VMT прописывается на этапе компиляции. Ясный пень. Это не к тебе коммент, а к Flex Ferrum. Насчет варнинга - если есть желание, можно продолжить в привате, здесь как-то это странновато... |
Сообщ.
#1460
,
|
|
|
Цитата --Ins-- @ Не понял смысл фразы. Есть методы статические, есть - виртуальные. Статические ВСЕГДА вызываются по определенному на этапе компиляции адресу. Виртуальные - ВСЕГДА по адресу, определенному в рантайм. В плюсах есть разница. Если ты обращаешься к методу по т. н. неквалифицированному имени, а слева у тебя стоит указатель или ссылка на объект - тогда вызов будет виртуальным (если метод виртуальный). В остальных случаях вызов будет прямым. Т. е.: ![]() ![]() 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(); // прямой вызов //... |
Сообщ.
#1461
,
|
|
|
Цитата В плюсах есть разница. Если ты обращаешься к методу по т. н. неквалифицированному имени, а слева у тебя стоит указатель или ссылка на объект - тогда вызов будет виртуальным (если метод виртуальный). В остальных случаях вызов будет прямым. Ну и глупо значит сделано. Так как вызов в коде "не своей" реализации виртуального метода говорит о неправильно спроектированной архитектуре. |
Сообщ.
#1462
,
|
|
|
Цитата --Ins-- @ Ну и глупо значит сделано. Так как вызов в коде "не своей" реализации виртуального метода говорит о неправильно спроектированной архитектуре. Ну почему же? Становится вполне допустимым такой код: ![]() ![]() class Derived : public Base { public: void foo() { Base::foo(); // прямой вызов реализации метода foo из базового класса // реализация метода } }; // ... Derived d; d.foo(); // зачем здесь виртуализация вызова, если тип объекта доподлинно известен в точке вызова, и не может быть никаким другим? // ... |
Сообщ.
#1463
,
|
|
|
Flex Ferrum, правильно ли я понимаю, что для потомка с перекрытым виртуальным методом, есть возможность вызова реализации виртуального метода предка(ов)? Если да, то эта возможность провоцирует к написанию плохого объектного кода. Это позволяет обойти объектно-ориентированные принципы, в частности - полиморфизм, заменив их своими "поделками".
|
Сообщ.
#1464
,
|
|
|
Цитата --Ins-- @ Flex Ferrum, правильно ли я понимаю, что для потомка с перекрытым виртуальным методом, есть возможность вызова реализации виртуального метода предка(ов)? Если да, то эта возможность провоцирует к написанию плохого объектного кода. Это позволяет обойти объектно-ориентированные принципы, в частности - полиморфизм, заменив их своими "поделками". Правильно ли я понимаю, что острая заточка ножа позволят откромсать себе полпальца, а значит провоцирует на членовредительство? ![]() ![]() ![]() Добавлено А если серьезно, такие вещи можно сделать только намеренно (явно квалифицировав имя метода). "Случайно" написать плохой код у тебя не получится. А намеренно - ты это сделаешь и без таких возможностей. ![]() |
Сообщ.
#1465
,
|
|
|
Flex Ferrum
Угу. Знаете, как в одном анектоде... "Его последними словами были "Не бойся, дорогая, я уже сто раз так делал!"". ![]() ![]() Знаете почему в C/C++ чувствительный к регистру синтаксис? Добавлено Цитата А если серьезно, такие вещи можно сделать только намеренно (явно квалифицировав имя метода). "Случайно" написать плохой код у тебя не получится. А намеренно - ты это сделаешь и без таких возможностей. Лично я, намерянно никогда такого не делал и даже никогда мне такого не требовалось. Бо для меня это дикость (такая же, как и множественное наследование реализаций.). В грамотно спроектированной системе такого быть не должно. ![]() |
Сообщ.
#1466
,
|
|
|
Цитата --Ins-- @ Угу. Знаете, как в одном анектоде... "Его последними словами были "Не бойся, дорогая, я уже сто раз так делал!"". ![]() ![]() Знаете почему в C/C++ чувствительный к регистру синтаксис? Т. е., продолжая аналогию, всех мужиков, прошу прощения, надо кастрировать, т. к. они своим хозяйством чего доброго и изнасиловать могут. Ну ведь могут же? ![]() ![]() |
Сообщ.
#1467
,
|
|
|
Цитата Голова человеку дана чтобы думать - разве не так? Так. Только такая возможность его провоцирует не думать. Вы лучше объясните, какие мы преимущества от этой возможности получаем, какие недостатки - я сам вижу ![]() |
Сообщ.
#1468
,
|
|
|
Цитата --Ins-- @ Только такая возможность его провоцирует не думать. Вы лучше объясните, какие мы преимущества от этой возможности получаем, какие недостатки - я сам вижу ![]() Это каким же это образом она его провоцирует? |
Сообщ.
#1469
,
|
|
|
Все ваши аналогии кривоваты на мой взгляд
![]() ![]() Добавлено Цитата Это каким же это образом она его провоцирует? Я же говорил, что возможность вызова виртуального метода предка, который в данном классе был перекрыт, противоречит принципам объектно-ориентированного проектирования. Но так как это возможно, программист так и поступит (это же гораздо проще), вместо того, чтобы изначально правильно спроектировать систему, в которой такой необходимости нет. |
Сообщ.
#1470
,
|
|
|
Цитата --Ins-- @ Но так как это возможно, программист так и поступит (это же гораздо проще), вместо того, чтобы изначально правильно спроектировать систему, в которой такой необходимости нет. В том то и дело, что не проще. Для этого вместо Derived* b; b->SomeMethod() надо написать: Base* b; b->Base::SomeMethod(); Как видишь, телодвижений несколько, гм, больше. По этому и говорю - "случайно" воспользоваться этой возможностью равносильно тому, что ты "случайно" откромсаешь себе ножом полпальца. И второй момент - совсем новички о такой возможности просто не знают, т. к. в соответствующей литературе такая форма вызова метода не описывается. |