Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Закрытая темаСоздание новой темы Создание опроса
> Зачем нужен virtual – override, Ведь методы и без того замещаются 
V
    Опции темы
Rohoss
  Дата 5.7.2008, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начальник интернета
***


Профиль
Группа: Завсегдатай
Сообщений: 1308
Регистрация: 9.10.2006
Где: Matrix

Репутация: нет
Всего: 18



Код

  TMyClassA=class
  procedure Test; virtual;
  end;

  TMyClassB=class(TMyClassA)
  procedure Test; override;
  end;

procedure TMyClassA.Test;
begin
  ShowMessage('A');
end;

procedure TMyClassB.Test;
begin
  ShowMessage('B');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyClassB.Create.Test;
end;

Видим «В», также как и тут
Код

  TMyClassA=class
  procedure Test; 
  end;

  TMyClassB=class(TMyClassA)
  procedure Test; 
  end;

procedure TMyClassA.Test;
begin
  ShowMessage('A');
end;

procedure TMyClassB.Test;
begin
  ShowMessage('B');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyClassB.Create.Test;
end;




--------------------
Файловый менеджер Explorer.Net скачать  video
PM ICQ   Вверх
kemiisto
  Дата 5.7.2008, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 2
Всего: 160



Виртуальные методы представляют интерес с такой позиции: что произойдет, если виртуальный метод будет вызван посредством ссылки на базовый класс? Какую именно версию метода нужно вызвать, Delphi определяет по типу объекта, на который указывает эта ссылка, причем решение принимается динамически, во время выполнения программы. Следовательно, если имеются ссылки на различные объекты, будут выполняться различные версии виртуального метода. Другими словами, именно тип объекта, на который указывает ссылка (а не тип ссылки) определяет, какая версия виртуального метода будет выполнена. Таким образом, если базовый класс содержит виртуальный метод и из этого класса выведены производные классы, то при наличии ссылки на различные типы объектов (посредством ссылки на базовый класс) будут выполняться различные версии этого виртуального метода.

На твоём примере. Давай немного подправим твою последнюю процедурку:
Код

procedure TForm1.Button1Click(Sender: TObject);

procedure DoTest(Obj: TMyClassA);
begin
  Obj.Test;
end;

var
  A: TMyClassA;
  B: TMyClassB;
begin
  A := TMyClassA.Create;
  B := TMyClassB.Create;
  DoTest(A);
  DoTest(B);
end;


Теперь попробуй и почуствую разницу! В первом случае, происходит переопределение (overrriding), а во втором сокрытие метода базового класса. Результаты будут различны.

Это сообщение отредактировал(а) kemiisto - 5.7.2008, 11:07


--------------------
PM MAIL WWW GTalk Jabber   Вверх
Alexeis
Дата 5.7.2008, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 34
Всего: 459



kemiisto, гм.. виртуальные функции всегда должны перекрываться в наследниках, например директива override в C++ вообще отсутствует, вместе с механизмом введения новой виртуальной функции с тем же именем. В Delphi такой механизм есть, потому для него делема, чего применить по умолчанию директиву override или reintroduce, из-за этого он требует явного указания директивы. Я бы не сказал, что это сильно удобно, reintroduce используется в сотни раз реже, потому было бы лучше если бы компилятор по умолчанию использовал override  smile 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Beltar
Дата 7.7.2008, 07:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 0
Всего: 7



Я из-за этого override, точнее его отсутствия попадал на утечку памяти и AV, мой деструктор в др. случае обработчик оповещений просто не включались. :( Сейчас бы я с такой ерундой быстро разобрался, тем более, что включенный код в редакторе помечается, но тогда мне потребовалось время.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Snowy
Дата 7.7.2008, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 31
Всего: 484



Beltar, а ты читай варнинги компилятора - не будет таких проблем.
Они для того и сделаны, чтобы их читали, а не игнорировали.
PM MAIL   Вверх
PsiMagistr
Дата 31.12.2009, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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, если обе переменные  можно разными типами объявить?))))



--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
Alexeis
Дата 31.12.2009, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 34
Всего: 459



Цитата(PsiMagistr @  31.12.2009,  10:04 Найти цитируемый пост)
Отсюда вопрос. Зачем этот override, если обе переменные  можно разными типами объявить?))))

  Думаю, что вы просто не умеете применять полиморфизм. Приведение наследников к предком позволяет производить групповые операции над объектами разных классов имеющих общего предка. 
  Кроме того директива virtual без override создает новый виртуальный метод с таким же именем, т.е. фактически при вызове такого метода (из предка) будет вызван метод предка, а не наследника. Такие "финты ушами" имеют смысл, только при длинной цепочке наследования.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
PsiMagistr
Дата 31.12.2009, 11:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Alexeis , спасибо большое. Но дело тут в том, что если обе переменные объявлены,

 одна от класса предка другая от класса потомка:

var 

a1:cl1; // от предка
a2: cl2; // от потомка.



то директивы Virtual-Override становятся как будто не нужны . Все "как будто " работает и так.


Еще раз простите меня, только вчера коснулся концепции ООП. Может посоветуйте какие нибудь книги  специально по этой теме.

С Наступающим Вас!



Это сообщение отредактировал(а) PsiMagistr - 31.12.2009, 11:36


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
CodeMonkey
Дата 31.12.2009, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Цитата(PsiMagistr @  31.12.2009,  11:33 Найти цитируемый пост)
директивы Virtual-Override становятся как будто не нужны

Да.

Но вам об этом и говорят: речь идёт о ситуациях, когда у вас нет переменной конкретного класса, а только более общего. На практике это встречается намного чаще, чем вам сейчас кажется.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
PsiMagistr
Дата 31.12.2009, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Правильно ли я понял, что:

Существует возможность объявлять переменные род. класса, конструируя на их основе объекты всех дочерних классов? 


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
bems
Дата 31.12.2009, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



да.

Добавлено через 5 минут и 46 секунд
Цитата(PsiMagistr @  31.12.2009,  11:33 Найти цитируемый пост)
директивы Virtual-Override становятся как будто не нужны . Все "как будто " работает и так.
Ну это оч. простой случай, тут можно и без виртуальных методов обойтись (никто же не принуждает силой тебя использовать их). Но посмотри на чуит более сложный пример
Код

TMyClassA=class
  procedure Test; virtual;
  procedure DoTest;
  end;

TMyClassB=class(TMyClassA)
  procedure Test; override;
  end;

procedure TMyClassA.Test;
begin
  ShowMessage('A');
end;

procedure TMyClassA.DoTest;
begin
  ShowMessage('TMyClassA.DoTest');  
  Test
end;

procedure TMyClassB.Test;
begin
  ShowMessage('B');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TMyClassB.Create.DoTest;
end;

Тут мы вызываем метод, который в TMyClassB вообще не объявлен (он унаследован), но видим черты поведения от обоих классов (первое сообщение от А, второе от В)



--------------------
Обижено школьников: 8
PM MAIL   Вверх
Alexeis
Дата 31.12.2009, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 34
Всего: 459



Цитата(PsiMagistr @  31.12.2009,  13:12 Найти цитируемый пост)
Существует возможность объявлять переменные род. класса, конструируя на их основе объекты всех дочерних классов?  

  Например форма создает компоненты из ресурсов, при этом все объекты помещает в массив Components типа TComponent, кроме того те из них, которые имеют визуальное представление помещает в массив Controls типа TControls. Реальные классы ее не интересуют. Важно, что они как минимум компоненты, тогда у них есть все свойства и методы компонентов, а если они контролы, то их нужно оповещать о необходимости перерисовки и т.д. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
PsiMagistr
Дата 31.12.2009, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Уважаемый bems, большое спасибо! По моему уже что то проясняется. Единственное, что немного непонятно как получается вызов метода без создания переменной-указателя, через некую 3х ступенчатую конструкцию:


 ИмяКласса.Конструктор.Метод. 

"TMyClassB.Create.DoTest;"

Ваш код вплоне рабочий (проверенно) это просто вопрос от новенького. Я никогда не думал что можно и так вызывать.




--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
bems
Дата 31.12.2009, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



Ну конструктор возвращает объект (как функция). Этот объект можно куда-то присвоить, а можно сразу вызвать его метода, как в примере. Но дело в том что созданные объекты нужно уничтожить, а такой "трехступенчатый" вызов не даёт возможности это сделать, поэтому годится толкьо в качестве примера. Нужно делать так
Код

a := TMyClassA.Create;
try
  a.DoTest
finally
  a.Free
end

или так
Код

with TMyClassA.Create do
  try
    DoTest
  finally
    Free
  end;



--------------------
Обижено школьников: 8
PM MAIL   Вверх
PsiMagistr
Дата 31.12.2009, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 479
Регистрация: 31.12.2009

Репутация: 1
Всего: 1



Мне интересно, что как бы мы не объявляли эту переменную от предка:

Код

var a:MyClassA;



 //или от потомка:

Код

var a:MyClassB;


Без дирректив virtual-override будет вызываться только родительская реализация метода.

А в приведенном мной простом примере (см. выше. самое начало) объявление указателя-переменной от потомка почему то позволяло пользоваться реализацией потомка без директив...

Это сообщение отредактировал(а) PsiMagistr - 31.12.2009, 17:17


--------------------
"Арфы нет? Возьмите бубен!

Ребята, будем жить!"

 (с) "В бой идут одни старики"

---

"ИЕ" - один из самых сумасшедших браузеров в нашей галактике.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Закрытая темаСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0946 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.