Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2002.09.30;
Скачать: [xml.tar.bz2];

Вниз

Что такое виртуальный метод ?   Найти похожие ветки 

 
Nega   (2002-09-01 13:29) [0]

Ну то есть когда после заголовка функции идет virtual; ?

И чем он отличается от обычного ?


 
Anatoly Podgoretsky   (2002-09-01 13:49) [1]

Это когда написано одно, а на самом деле другое
вместо твоего подставляется метод от наследника


 
Nega   (2002-09-01 16:07) [2]

Так ведь наследник и так может переопределить метод директивой override. Или это не то ?


 
Anatoly Podgoretsky   (2002-09-01 16:14) [3]

Нет не может


 
Nega   (2002-09-01 17:02) [4]

КАК ЭТО НЕ МОЖЕТ ? Всегда переопределяли, а оказывается не может ?
Ведь можно переопределить конструктор, деструктор и любую функция процедуру !
А как же

procedure proc; override;

procedure proc;
begin
inherited proc;
{инициализация наследника}
end;

?!?!


 
ZZ   (2002-09-01 17:10) [5]

А до этого было
procedure proc; virtual; :))


 
Anatoly Podgoretsky   (2002-09-01 17:17) [6]

Влт от этого virtual он и хочет уйти


 
TTCustomDelphiMaster   (2002-09-01 17:35) [7]

Nega (01.09.02 13:29)
Почитайте
http://www.compress.ru/Article.asp?id=767


 
drpass   (2002-09-01 18:19) [8]

Если метод родительского класса был объявлен, как virtual, то ты его можешь переопределить с помощью директивы override.
Если не был, то переопределить не можешь. Ты можешь только перекрыть его в своем классе, что не одно и тоже


 
Nega   (2002-09-01 18:51) [9]

А какая разница, переопределю я его или перекрою ?
Наверное, если перекрыть, то в приложении будет вызываться новый метод, а сам класс будет вызывать старый метод... или как ?

И еще. А если перекрыть виртуальный метод без директивы override что будет ?


 
Anatoly Podgoretsky   (2002-09-01 19:03) [10]

Будет ошибка, почему бы не запусить компилятор и не проверить?


 
Nega   (2002-09-01 19:15) [11]

Ошибка говорите ?

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TClass1 = class
procedure Func; virtual;
end;
TClass2 = class(TClass1)
procedure Func;
end;
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

procedure TClass1.Func;
begin
showmessage("Test");
end;

procedure TClass2.Func ;
begin
showmessage("Test2");
end;

{$R *.DFM}

end.


При компиляции ошибок нет.

Предупреждения: Method "Func" hides virtual method of base type "TClass1"

А если метод Func объявленный в TClass1 не виртуальный, то никаких предупреждений нету даже.

Объясните, пожалуйста, доступно, что к чему. А то я запутался...


 
Феликс   (2002-09-01 20:12) [12]

Это все евреи! Они во всем виноваты! :)


 
Anatoly Podgoretsky   (2002-09-01 20:20) [13]

Вот про это и речь
Method "Func" hides virtual method of base type "TClass1"

Теперь попробуй override без virtual согласно Nega (01.09.02 16:07)


 
Криворукий   (2002-09-01 22:18) [14]

Попробую объяснить популярно.

Прежде всего, ты должен понимать, что существуют объекты и существуют ссылки на объекты.
Сам объект он один и он принадлежит к некоторому конкретному классу.
Ссылок же на него может быть много, и они могут быть объявлены не как ссылка на конкретный класс объекта, а как ссылка на любой класс-предок.

Напр.
var
Comp: TComponent;
Obj: TObject;
begin
Comp := TEdit.Create(AnyForm);
Obj := Comp;
// Объект - это то, на что ссылаются Comp и Obj - они физически являются указателями.
// Реальный класс объекта - TEdit;
// В Дельфи мы можем манипулировать только ссылками на объект
end;

Предположим, у базового класса TBase есть невиртуальный метод HelloWorld c вылезающим
соответствующим сообщением.
Когда потомок TDerived определяет метод с таким же именем HelloWorld, это называется
переопределением метода.

При этом происходит одна очень неприятная вещь -
то какой метод будет вызван, будет определятся не самим объектом,
а тем, как объявлена на него ссылка.

var
B: TBase;
D: TDerived;
begin
B := TDerived.Create;
D := B as TDerived; // и B и D указывают на один и тот же объект

B.HelloWorld; // Hello, World!
D.HelloWorld; // Don"t trouble troubles until troubles trouble you.
end;

Такого эффекта обычно стараются избегать.
(Хотя с сях на этом эффекте основываются даже кое-какие трюки).

Если бы этот метод в базовом классе был объявлен как virtual, а в потомке - как override (перекрытый) - то в обоих случаях, независимо от того, как объявлена ссылка, результат был бы одинаковый - "Don"t trouble troubles until troubles trouble you"
и определялся бы он фактическим классом объекта - TDerived.

НО ЭТО РАБОТАЕТ ТОЛЬКО В ТАКОЙ КОНФИГУРАЦИИ - в базовом virtual,
а в потомках override;

Любая другая комбинация директив приведёт к первому варианту, и компилятор скажет тебе, что метод потомка скрывает (Hides) метод предка.


 
Nega   (2002-09-01 22:45) [15]

Криворукий, спасибо. Только вот что непонятно:

var
B: TBase;
...
B := TDerived.Create;

Разве так можно ?!

B - ссылка на объект типа TBase, а конструктор применяют от другого класса TDerived. Это не ошибка ?


 
Юрий Зотов   (2002-09-01 22:59) [16]

Если
TDerived=class(TBase)
то это не ошибка. В VCL такое сплошь и рядом (например, объявлено TStrings, а реально создается TStringList).

Важно понимать, что запись
B: TBase;
означает, что B - это ЛЮБОЙ TBase. А все потомки TBase - это тоже TBase.


 
Криворукий   (2002-09-01 23:09) [17]

Нет, не ошибка.
Так можно, и часто именно так и делают.
Типом ссылки может быть любой класс-предок.
Ссылка на TDerived может быть любого из типов: TObject, TBase, TDerived

TBase = class(TObject)
procedure HelloWorld; virtual;
end;

TDerived = class(TBase)
procedure HelloWorld; override;
end;

var
O: TObject;
B: TBase;
D: TDerived;

// Любой из вариантов рабочий
O := TDerived.Create;
B := TDerived.Create;
D := TDerived.Create;


 
Nega   (2002-09-02 16:58) [18]

1) Блин. Не понимаю.

Вот например:

TDerived = class(TBase)
a:integer;
end;

То есть в TDerived появилось новое свойство "a". И если в конструкторе инициализируется ее значение:

constructor TDerived.Create;override;
inherited TBase.Create;
i:=0;
end;

Но если O:TBase, а конструктор от TDerived, то:

O:=TDerived.Create;

что делает эта строчка i:=0; ?Ведь никакого свойства i у TBase нету ?

2) Все конструкторы виртуальные ? Сплошь и рядом вижу переопределение конструкторов директивой override.


 
MBo   (2002-09-02 17:20) [19]

1. у tbase нету, а объект О создается типа TDerived , для него эта строчка выполняется. однако если ты задашь свойство или public метод в TDerived, то для О, созданногго таким образом, к нему обратиться нельзя простым способом, только через приведение типов
If O is TDerived then
TDerived(O).DerivedProp:=2;

2. не все, но начиная с TComponent - все виртуальные


 
Nega   (2002-09-02 22:48) [20]

А верна ли такая конструкция:

TBase=Class
constructor Create;
...
end;

TDerived=Class(TBase)
constructor Create;virtual;
end;


 
iZEN   (2002-09-04 00:49) [21]

Виртуальный метод -- это функция, код которой вызывается на выполнение по указателю, определяемому на этапе исполнения из таблицы виртуальных методов (одна таблица на каждый класс; ссылка на таблицу есть у каждого экземпляра). Это обеспечивает прилинкованный к приложению код работы с RTTI (Run Time Type Identification/Information).



Страницы: 1 вся ветка

Форум: "Потрепаться";
Текущий архив: 2002.09.30;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.008 c
3-98003
Макс
2002-09-10 14:36
2002.09.30
LookUp - поля с большими массивами информации


4-98409
AFROLOV
2002-08-15 14:07
2002.09.30
Как быстро убить приложение?


3-97954
RDA
2002-09-08 11:13
2002.09.30
Локализация EMS QuickDesk 2.0


1-98115
lovres
2002-09-20 10:02
2002.09.30
Вопрос по RadioGroup


1-98178
explorer
2002-09-18 09:31
2002.09.30
При создании формы вызвать событие закрытия формы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский