![]() |
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]() ![]() ![]() |
|
Rohoss |
|
||||
![]() Начальник интернета ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1308 Регистрация: 9.10.2006 Где: Matrix Репутация: нет Всего: 18 |
Видим «В», также как и тут
|
||||
|
|||||
kemiisto |
|
|||
![]() Дикий Кот. =^.^= ![]() ![]() ![]() ![]() Награды: 1 Профиль Группа: Участник Клуба Сообщений: 3292 Регистрация: 29.7.2007 Репутация: 2 Всего: 160 |
Виртуальные методы представляют интерес с такой позиции: что произойдет, если виртуальный метод будет вызван посредством ссылки на базовый класс? Какую именно версию метода нужно вызвать, Delphi определяет по типу объекта, на который указывает эта ссылка, причем решение принимается динамически, во время выполнения программы. Следовательно, если имеются ссылки на различные объекты, будут выполняться различные версии виртуального метода. Другими словами, именно тип объекта, на который указывает ссылка (а не тип ссылки) определяет, какая версия виртуального метода будет выполнена. Таким образом, если базовый класс содержит виртуальный метод и из этого класса выведены производные классы, то при наличии ссылки на различные типы объектов (посредством ссылки на базовый класс) будут выполняться различные версии этого виртуального метода.
На твоём примере. Давай немного подправим твою последнюю процедурку:
Теперь попробуй и почуствую разницу! В первом случае, происходит переопределение (overrriding), а во втором сокрытие метода базового класса. Результаты будут различны. Это сообщение отредактировал(а) kemiisto - 5.7.2008, 11:07 -------------------- |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 34 Всего: 459 |
kemiisto, гм.. виртуальные функции всегда должны перекрываться в наследниках, например директива override в C++ вообще отсутствует, вместе с механизмом введения новой виртуальной функции с тем же именем. В Delphi такой механизм есть, потому для него делема, чего применить по умолчанию директиву override или reintroduce, из-за этого он требует явного указания директивы. Я бы не сказал, что это сильно удобно, reintroduce используется в сотни раз реже, потому было бы лучше если бы компилятор по умолчанию использовал override
![]() -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
Beltar |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 627 Регистрация: 11.1.2006 Репутация: 0 Всего: 7 |
Я из-за этого override, точнее его отсутствия попадал на утечку памяти и AV, мой деструктор в др. случае обработчик оповещений просто не включались. :( Сейчас бы я с такой ерундой быстро разобрался, тем более, что включенный код в редакторе помечается, но тогда мне потребовалось время.
-------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. ![]() Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере. |
|||
|
||||
Snowy |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 11363 Регистрация: 13.10.2004 Где: Питер Репутация: 31 Всего: 484 |
Beltar, а ты читай варнинги компилятора - не будет таких проблем.
Они для того и сделаны, чтобы их читали, а не игнорировали. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребята, у меня такой вопрос, связанный с override.
В общем целом. Объявляем класс cl1 и дочерний от него класс cl2. В классе cl1 Virtual-им какой нить метод, в классе cl2 перекрываем его директивой override. Если мы объявим теперь две переменные var a1 : cl1; и var a2: cl2; А потом вызовем конструкторы a1:=cl1.Create; a2:= cl2.Create; Вызванные потом методы будут и без овверрайда пахать. А вот если обе переменные var a1:cl1; a2:cl1; А потом вызовем конструкторы a1:=cl1.Create; a2:= cl2.Create; то сработает override. Т.е. обе переменные принадлежат к одному родительскому классу (только конструкторы разнятся )... Отсюда вопрос. Зачем этот override, если обе переменные можно разными типами объявить?)))) -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 34 Всего: 459 |
Думаю, что вы просто не умеете применять полиморфизм. Приведение наследников к предком позволяет производить групповые операции над объектами разных классов имеющих общего предка. Кроме того директива virtual без override создает новый виртуальный метод с таким же именем, т.е. фактически при вызове такого метода (из предка) будет вызван метод предка, а не наследника. Такие "финты ушами" имеют смысл, только при длинной цепочке наследования. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Alexeis , спасибо большое. Но дело тут в том, что если обе переменные объявлены,
одна от класса предка другая от класса потомка: var a1:cl1; // от предка a2: cl2; // от потомка. то директивы Virtual-Override становятся как будто не нужны . Все "как будто " работает и так. Еще раз простите меня, только вчера коснулся концепции ООП. Может посоветуйте какие нибудь книги специально по этой теме. С Наступающим Вас! Это сообщение отредактировал(а) PsiMagistr - 31.12.2009, 11:36 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
CodeMonkey |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Да. Но вам об этом и говорят: речь идёт о ситуациях, когда у вас нет переменной конкретного класса, а только более общего. На практике это встречается намного чаще, чем вам сейчас кажется. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Правильно ли я понял, что:
Существует возможность объявлять переменные род. класса, конструируя на их основе объекты всех дочерних классов? -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
да.
Добавлено через 5 минут и 46 секунд
Тут мы вызываем метод, который в TMyClassB вообще не объявлен (он унаследован), но видим черты поведения от обоих классов (первое сообщение от А, второе от В) -------------------- Обижено школьников: 8 |
||||
|
|||||
Alexeis |
|
|||
![]() Амеба ![]() Профиль Группа: Админ Сообщений: 11743 Регистрация: 12.10.2005 Где: Зеленоград Репутация: 34 Всего: 459 |
Например форма создает компоненты из ресурсов, при этом все объекты помещает в массив Components типа TComponent, кроме того те из них, которые имеют визуальное представление помещает в массив Controls типа TControls. Реальные классы ее не интересуют. Важно, что они как минимум компоненты, тогда у них есть все свойства и методы компонентов, а если они контролы, то их нужно оповещать о необходимости перерисовки и т.д. -------------------- Vit вечная память. Обсуждение действий администрации форума производятся только в этом форуме гениальность идеи состоит в том, что ее невозможно придумать |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Уважаемый bems, большое спасибо! По моему уже что то проясняется. Единственное, что немного непонятно как получается вызов метода без создания переменной-указателя, через некую 3х ступенчатую конструкцию:
ИмяКласса.Конструктор.Метод. "TMyClassB.Create.DoTest;" Ваш код вплоне рабочий (проверенно) это просто вопрос от новенького. Я никогда не думал что можно и так вызывать. -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Ну конструктор возвращает объект (как функция). Этот объект можно куда-то присвоить, а можно сразу вызвать его метода, как в примере. Но дело в том что созданные объекты нужно уничтожить, а такой "трехступенчатый" вызов не даёт возможности это сделать, поэтому годится толкьо в качестве примера. Нужно делать так
или так
-------------------- Обижено школьников: 8 |
||||
|
|||||
PsiMagistr |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Мне интересно, что как бы мы не объявляли эту переменную от предка:
//или от потомка:
Без дирректив virtual-override будет вызываться только родительская реализация метода. А в приведенном мной простом примере (см. выше. самое начало) объявление указателя-переменной от потомка почему то позволяло пользоваться реализацией потомка без директив... Это сообщение отредактировал(а) PsiMagistr - 31.12.2009, 17:17 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||
|
|||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
ну у потомка же нет собственного метода DoTest, поэтому в любом случае вызывается унаследованный от предка. А внутри него вызов Test (если убрать виртуальность) означает вызов из того же класса - остальные там просто не видны.
-------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
||||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Таким образом на основании двух примеров формируем след вопрос:
Пример первый. Описание классов от bems
Пример второй
На мой взгляд это рождает некоторую путаницу... Т.е. я полагал, что без этих директив, род. методы не должны перекрываться по любому. bems, Alexsis спасибо большое за примеры. Bems, Насчет вызова родительского метода у дочернего класса я понял, собственный у него отсутствует, он пользуется тем что есть (унаследованным). Это сообщение отредактировал(а) PsiMagistr - 31.12.2009, 19:12 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||
|
|||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
-------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Bems, большое спасибо, вы мне просто глаза открыли, честное слово.
![]() Таким образом: Существует родительский класс "А" и класс-наследник "В" В классе "А" прописан некоторый метод C-metod, вызывающий в процессе выполнения дополнительно метод D-metod того же класса. Класс наследник В обладает собственным D-metodom, отличным по исполнению от родительского. Но собственным методом С-metod, класс В не обладает. Этот метод переходит к нему по правам наследования. Если объекту класса B необходимо исполнить унаследованный С-metod, метод D-metod, вызываемый внутри такого С-metod необходимо сделать виртуальным (Virtual) в объявлении класса родителя, а затем переопределить (override), в объявлении потомка, иначе будет выполнен D-metod класса А. Т.е. пара virtual-override используется, когда когда наследуемому методу необходимо выполнить чужеродные ему по изначальной природе элементы (методы дочерних классов). Будь у класса B собственный метод С-metod, он бы просто сокрыл родительский (пропиши rentroduce), чтобы компилятор не ругался. Это сообщение отредактировал(а) PsiMagistr - 1.1.2010, 11:53 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Ничего не понял
![]() Добавлено через 38 секунд Не ты. Я ничего не понял в твоём посте -------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Попробую объяснить на примере твоего же кода, боюсь выйдет некоторый флуд, но я удалю потом:
Существует родительский класс TMyClassA и класс-наследник TMyClassB. В классе TMyClassA прописан некоторый метод DoTest, вызывающий в процессе выполнения, кроме всего прочего свой метод Test. Класс наследник TMyClassB обладает собственным методом Test отличным по исполнению от родительского Test. Но собственным методом DoTest класс TMyClassB не обладает. Этот метод переходит к нему по правам наследования. Если объекту класса TMyClassB необходимо исполнить унаследованный DoTest , метод Test, вызываемый внутри такого DoTest необходимо сделать виртуальным (Virtual) в объявлении класса родителя, а затем переопределить (override), в объявлении потомка, иначе будет выполнен Test TMyClass.Test, вместо TMyClassB.Test . Т.е. пара virtual-override используется, когда когда наследуемому методу необходимо выполнить чужеродные ему по изначальной природе элементы (методы дочерних классов). Будь у класса TMyClassB собственный метод DoTest, он бы просто сокрыл родительский (пропиши rentroduce), чтобы компилятор не ругался. Это сообщение отредактировал(а) PsiMagistr - 1.1.2010, 19:47 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Продолжаю изучать теорию ООП. Изваял микропрограмму, использующую классы и Virtual-override директивы.
Программа направлена на вычисление объема геометрических фигур: призмы с квадратным основанием и призмы с круглым основанием (цилиндр). Согласно математике объем данных фигур можно получить по общей формуле: Объем:= ПлощадьФигуры*ВысотуФигуры. Поэтому метод GetVolume (Получение объема) является общим для всех классов. Однако этот общий метод использует метод GetArea (ПолучениеПлощади), реализация которого является различной для дочерних классов "Круг" (TDisk) и "Квадрат" (TSqr), поэтому метод GetArea объявлен виртуальным. Переходим в раздел глобальных переменных и опишем класс родоначальник:
Разработано и тестировано мною в среде Дельфи 6. Попробуйте убрать Virtual-override, раскомментировать реализацию GetArea для класса Figura и посмотреть, что получится. ![]() Это сообщение отредактировал(а) PsiMagistr - 3.1.2010, 17:43 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Для случаев вроде Figura.GetArea нужно использовать abstract и убрать пустую реализацию вообще
-------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Bems, а что за команда Abstract, объясни нубику, плиз, а то я только 3 дня, как пытаюсь понять ООП.
-------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
в объявлении класса Figura метод GetArea объявляешь как
Его пустую реализацию удаляешь вообще. Дочерние классы не меняются -------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Bems, благодарю. Ты мне очень-очень сильно помогаешь.
Насколько я понимаю, главное этот абстрактный метод не вызвать где нибудь напрямую, чтоб он о свою несуществующую реализацию не споткнулся. ))). Насколько теперь я могу понимать, если б классы TDisc и TSqr имели свою реализацию GetVolume, а не наследованную родительскую, это было б не перекрытие (override), а просто сокрытие, так? А в чем различие между override и overload? Это сообщение отредактировал(а) PsiMagistr - 3.1.2010, 16:30 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
ну вот тут же ты вызываешь
Но да, если вызвать это на самом предке, то будет ошибка EAbstractError И это очень хорошо ![]() Потому что это в обоих случаях ошибка, но при Abstract тебе на нее покричат, а без Abstract прога просто будет работать не так как надо (потому что в лоюбом случае не научена она считать объем какой-то неконкретной абстрактной финуры) А почти ничего общего. И к ООП не относится. И один топик - один вопрос. -------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
А какова практическая разница между Virtual и Dynemic?
-------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Практической нет. Dynamic занимает меньше памяти при некоторых условиях, но работает немного медленней. Но это всё не заметно на практике. Используй dynamic там где точно знаешь что без него никак, и virtual во всех остальных случаях.
И еще: методы обработки сообщений (те что с директивой message) на самом деле динамические, хоть объявляются без dynamic -------------------- Обижено школьников: 8 |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребята, я прошу прощения за некоторый оффтоп, столкнулся со следующей задачей:
Есть несколько картинок (класс TImage) с изображениями в них. При нажатии на какую либо картинку, внешний вид ее должен меняться, показывая, что картинка выбрана. Когда же мы нажимаем на след. картинку, выбирается она, а первая возвращается в исходное положение. Таким образом выбрать можно только одну картинку, плитки как бы переключаются между собой. Как возможно решить данный вопрос поизящнее? -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Рамку вокруг TImage делать, положив TImage на подкладку, например. PS. Можно и тему отдельную создать было. -------------------- |
|||
|
||||
PsiMagistr |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо, Демо. Рамка рамкой, но вопроса это не решает. Главное, как заставить совершать переключения? Т.е. одна картинка "нажата" , все остальные отжаты. Вот в чем суть. -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Это разве проблема - пробежаться по объектам, отключить выделение всех, включить тот, на который щёлкнули мышкой? Это сообщение отредактировал(а) Демо - 14.1.2010, 14:19 -------------------- |
|||
|
||||
bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Модератор: один топик - один вопрос!
-------------------- Обижено школьников: 8 |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Delphi: Для новичков" | |
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |