Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.09.30;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.016 c
1-98217
delpher_gray
2002-09-18 19:57
2002.09.30
Как не допустить закрытие консольного приложения ?


3-97955
ang
2002-09-06 12:04
2002.09.30
Insert, Update с MS через ADO?


1-98080
Борис
2002-09-19 15:07
2002.09.30
Помогите обратится к компоненту, расположенному на другой форме!


14-98351
billybons
2002-09-03 10:20
2002.09.30
сетевой прикол


14-98348
RV
2002-09-06 11:48
2002.09.30
есть ли