Форум: "Потрепаться";
Текущий архив: 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.007 c