Форум: "Основная";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
ВнизOverriding versus hiding Найти похожие ветки
← →
Bless © (2005-02-02 14:36) [0]Процитирую целиком текст справки из сабжевого раздела.
If a method declaration specifies the same method identifier and parameter signature as an inherited method, but doesn"t include override, the new declaration merely hides the inherited one without overriding it. Both methods exist in the descendant class, where the method name is statically bound. For example,
type
T1 = class(TObject)
procedure Act; virtual;
end;
T2 = class(T1)
procedure Act; // Act is redeclared, but not overridden
end;
var
SomeObject: T1;
begin
SomeObject := T2.Create;
SomeObject.Act; // calls T1.Act
end;
Объясните пожалуйста, почему строчка SomeObject.Act приводит к вызову метода Act из класса T1?
← →
REA (2005-02-02 14:42) [1]Компилятор знает, что SomeObject: T1 и вызывает метод T1.Act. Про метод T2.Act ему не известно в контексте этого объекта.
← →
icWasya © (2005-02-02 15:24) [2]если написать так
type
T1 = class(TObject)
procedure Act; virtual;
end;
T2 = class(T1)
procedure Act;overridde; end;
var
SomeObject: T1;
begin
SomeObject := T2.Create;
SomeObject.Act; // calls T2.Act
end;
то будет щастье
← →
Bless © (2005-02-02 16:09) [3]REA[1]>
Компилятор знает, что SomeObject: T1 и вызывает метод T1.Act. Про метод T2.Act ему не известно в контексте этого объекта.
Как это ничего не известно? SomeObject.ClassType=T2.
icWasya © (02.02.05 15:24) [2]
то будет щастье
Это я и сам знаю. Только я не об этом спрашивал.
← →
REA (2005-02-02 16:52) [4]SomeObject.ClassType это на момент выполнения. А на момент компиляции неизвестно, что попадет в эту переменную, поэтому компилятор не делает предположений относительно содержимого переменной, а вызывает метод по известному адресу. К тому же ему это ни к чему - метод не перекрыт и имеет право на жизнь.
Компилятор вызывает метод не пользуясь таблицей виртуальных методов - т.е. по фиксированному смещению, а не смещению прописанному в таблице виртуальных методов.
← →
Владислав © (2005-02-02 17:03) [5]Судя по всему, Вам нужно познакомиться с разницей в вызовах виртуальных и невиртуальных методов.
← →
Bless © (2005-02-02 17:48) [6]Владислав © (02.02.05 17:03) [5]
Кстати, "Вы" - это черезчур :)
← →
Bless © (2005-02-02 18:09) [7]Вот блин, потерялся один пост.
Повторяю:
>Владислав © (02.02.05 17:03) [5]
Судя по всему, Вам нужно познакомиться с разницей в вызовах виртуальных и невиртуальных методов.
Это вряд ли (хотя чем черт не шутит). Ведь если поменять в посте [0]
T2 = class(T1)
procedure Act; // Act is redeclared, but not overridden
end;
на
T2 = class(T1)
procedure Act; virtual; // Act is redeclared, but not overridden
end;
то результат останется тем же.
REA (02.02.05 16:52) [4]
А на момент компиляции неизвестно, что попадет в эту переменную, поэтому компилятор не делает предположений относительно содержимого переменной, а вызывает метод по известному адресу.
Ну пускай даже компилятору неизвестно, что попадет в эту переменную. Но как он может подставить вызов метода по известному адресу, если этот метод - виртуальный? Что-то я сильно сомневаюсь, что компилятор вдруг решил обратиться к виртуальному методу не по таблице виртуальных методов а по фиксированному смещению. Это есть в справке?
← →
Владислав © (2005-02-02 18:37) [8]Ну пускай даже компилятору неизвестно, что попадет в эту переменную. Но как он может подставить вызов метода по известному адресу, если этот метод - виртуальный? Что-то я сильно сомневаюсь, что компилятор вдруг решил обратиться к виртуальному методу не по таблице виртуальных методов а по фиксированному смещению. Это есть в справке?
В точку. Просто в [4] некорректное утверждение.
Вот у тебя и вызывается виртуальный метод T1. Потому что в таблице именно он и есть. Если бы написал override, то там был бы метод T2.
Еще раз прочти [5].
← →
Bless © (2005-02-03 09:10) [9]>Еще раз прочти [5]
Зачем? Причем тут статические методы? Я же написал (и проверил, кстати), что если метод T2.act сделать виртуальным, то ничего не изменится.
>Вот у тебя и вызывается виртуальный метод T1. Потому что в
>таблице именно он и есть. Если бы написал override, то там был бы
>метод T2.
Так он и так там есть! Не в виртуальной таблице правда, поскольку он статический, но все-равно есть. И его тоже можно вызвать. Например, вот так: Т2(SomeObject).Act. Но почему сразу вызывается не он? Как компилятор рассуждает?
Для простоты переделаю исходный пример:
type
T1 = class(TObject)
procedure Act; virtual;
end;
T2 = class(T1)
procedure Act; VIRTUAL; //!!!!!!!!!!!!!
end;
var
SomeObject: T1;
begin
SomeObject := T2.Create;
SomeObject.Act; // calls T1.Act
end;
Теперь в таблице виртуальных методов класса T2 присутствуют два метода Act (тоже проверил): один унаследованный и один свой. Почему в примере вызвается унаследованный?
← →
Владислав © (2005-02-03 09:14) [10]Знаешь, я больше повторяться не буду. Вот если после прочтения соответствующей документации у тебя появится желание продолжить тему, с удовольствием поучаствую.
← →
REA (2005-02-03 09:59) [11]Это разные методы. Ты не заменил метод (override) в таблице, а добавил второй с тем же именем. По-хорошему надо бы блокировать такие попытки, но компилятор видимо надеется, что программист знает, что делает.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.039 c