
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.188] |
![]() |
|
Страницы: (117) « Первая ... 95 96 [97] 98 99 ... 116 117 ( Перейти к последнему сообщению ) |
Сообщ.
#1441
,
|
|
|
Цитата Убери директиву overload у предка. Потому что обычно ее там нет. Понятно, не додумался. Вообще, это как-то неправильно по-моему. Зачем выдавать варнинг, что скрывается предыдущее объявление, если на самом деле оно не скрывается? |
Сообщ.
#1442
,
|
|
|
Цитата --Ins-- @ Вообще, это как-то неправильно по-моему. Зачем выдавать варнинг, что скрывается предыдущее объявление, если на самом деле оно не скрывается? Почему не скрывается? Скрывается. Это просто вежливость: ты объясняешь компилятору, что это ты не ошибся в объявлении параметров и имени метода, а именно так ты и хочешь. Одной директивы overload недостаточно для этого, мало ли, может, ты еще один метод в потомке напишешь ![]() |
Сообщ.
#1443
,
|
|
|
Я понимаю, что reintroduce нужен для того, чтобы заткнуть рот Delphi, мол я знаю, что делаю. Но по-моему Delphi иногда врет, говоря, что декларация метода скрывается. Что-то я вообще запутался
![]() ![]() ![]() T1 = class(TObject) procedure Test(I: Integer); virtual; end; T2 = class(T1) procedure Test(S: string); overload; virtual; procedure Test(E: TObject); overload; virtual; end; Ничего не скрывается. А в этом: ![]() ![]() 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; Тот, что с целочисленным параметром - скрывается. И даже reintroduce не помогает |
Сообщ.
#1444
,
|
|
|
У меня орет о скрытии в обоих случаях
![]() |
Сообщ.
#1445
,
|
|
|
Цитата У меня орет о скрытии в обоих случаях Орет то оно в обоих. Но в первом случае, procedure Test(I: Integer); virtual; я по прежнему могу вызвать. Врет, собака! ![]() |
Сообщ.
#1446
,
|
|
|
Ты его и во втором случае спокойно можешь вызвать.
![]() Варнинг говорит не о невозможности вызова, а о возможной ошибке. Если бы вызов виртуального метода предка из потомка был невозможен, ты бы предупреждением не отделался! |
Сообщ.
#1447
,
|
|
|
Romkin, тут ты не прав. Именно скрывается метод предка (о чем текст варнинга и говорит), что делает невозможным его вызов без приведения типа. Смотри:
Скомпилируй у себя: ![]() ![]() T1 = class(TObject) procedure Test(I: Integer); virtual; end; T2 = class(T1) procedure Test(S: String); virtual; end; ... procedure TForm1.FormCreate(Sender: TObject); var o: T2; s: String; i: Integer; begin o := T2.Create; o.Test(s); o.Test(i); o.Free; end; Добавлено Именно для таких случаев и была введена reintroduce, чтобы подтвердить, что ты знаешь что делаешь, когда скрываешь виртуальный метод предка. |
Сообщ.
#1448
,
|
|
|
Ндаааааа.... Вот у вас проблемы то...
![]() |
Сообщ.
#1449
,
|
|
|
Цитата Ндаааааа.... Вот у вас проблемы то... override, reintroduce... С выделенным словом как-раз никаких проблем нет. Видимо имелось в виду overload - так эта фича пришла в Delphi из C/C++ ![]() Я не понимаю, зачем reintroduce в данном конкретном случае. Мы ведь ничего не собираемся скрывать, а просто объявить одноименный метод, которы будет доступен наряду с предыдущими объявлениями. Зачем тогда подавлять варнинг о скрытии? Хотя допускаю, что в мои рассуждения закрался "жучок" ![]() |
Сообщ.
#1450
,
|
|
|
--Ins--, ну а overload где? в #1456 оно есть, а тут вдруг исчезло. Да, reintroduce не имеет особого отношения к overload.
Я понял, о чем ты говорил. Компилятор орет невзирая на наличие overload о сокрытии из-за независимости директив. Ведь ты можешь в будущем написать потомка этого потомка, и никто не знает, что тебе там в очередной раз взбредет в голову ![]() |
Сообщ.
#1451
,
|
|
|
--Ins--, мне, как прожженному плюсовику, все эти рассуждения в принципе странновато читать, т. к., судя по всему, в плюсах система разграничения видимости имен и перегрузки/перекрытия методов в принципе иначе работает. А потому суть решаемой проблемы не совсем понятно. В частности, я всегда предполагал (и продолжаю предполагать), что виртуальность метода играет роль только тогда, когда ты вызываешь метод, имея на руках указатель на базовый класс. Тогда работает полиморфизм времени выполнения. Относительно производного (листового) класса совершенно не важно - является метод виртуальным или нет - в любом случае при вызове механизм виртуализации задействован не будет. Отдельный разговор - это перекрытие/сокрытие имен методов. Но тут виртуальность совершенно не причем, т. к. эти механизмы исключительно compile-time, и управляют видимостью сигнатур методов. По крайней мере, так в С++.
|
Сообщ.
#1452
,
|
|
|
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, ничего не скрывается? В чем принципиальное отличие? Если на первый вопрос ответ "потому что метод виртуальный, а для них все иначе", то следующий вопрос - а какая разница, виртуальный он или нет, если как справедливо заметил Flex Ferrum, эти механизмы (скрытия и вызова метод в зависимости от параметров) исключительно compile-time? |
Сообщ.
#1453
,
|
|
|
Flex Ferrum, да, похоже, иначе все там у вас работает
![]() То есть в Delphi ты можешь прервать и начать заново цепочку наследования виртуального метода, в частности, конструктора, но это не приводит к серьезным последствиям из-за того, что ты всегда можешь явно определить имеющийся класс. То есть, возможен фокус вида ![]() ![]() T1 = class(TObject) procedure Test(I: Integer); virtual; end; T2 = class(T1) procedure Test(I: Integer); reintroduce; virtual; end; Но фактически такое объявление имеет смысл только для конструктора, как показал --Ins--. По крайней мере, другие случаи мне в голову не приходят. |
Сообщ.
#1454
,
|
|
|
Цитата В Delphi еще постоянно примешивается RTTI и виртуальные конструкторы. Дааа, не повезло ребятам... ![]() |
Сообщ.
#1455
,
|
|
|
Цитата Romkin @ и оба метода будут достижимы для вызова. Но фактически такое объявление имеет смысл только для конструктора, как показал --Ins--. По крайней мере, другие случаи мне в голову не приходят. А что значит "достижимы для вызова"? Вызов может быть из двух точек - со стороны базового класса, и со стороны производного. Виртуальность включается только тогда, когда ты вызываешь метод со стороны базового класса "по указателю". Т. е. на самом деле, на руках у тебя может быть один из его производных. Когда ты вызываешь метод для конкретного производного класса, никакой виртуальности нет - все уже известно на этапе компиляции. Так для какого рода вызова эти методы достижимы? |