![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Наследование и виртуальные функции [D5]
nastya © (2005-09-22 15:15:00)Привет! Киньте, пожалуйста, идею, где и как поискать ошибку. Я иссякла:(
Есть два класса TAnyDevice и его наследник TThisDevice. Общие функции TAnyDevice , конкретика у TThisDevice.
Есть две задачи прочитать и записать серийный номер. Чтение происходит нормально, а при записи Acsess Violation. На мой взгляд объявления и порядок выполнения для чтения и записи аналогичен. Но почему тогда ошибка только при записи??!! Вот объявления:
TAnyDevice
//запись данных в память
function WriteDataToEEprom(Addr:integer; Data:PByteArray;DataLen:word):boolean;
//чтение данных из памяти
function ReadDataFromEEprom(Addr:integer; var PData:PByteArray;DataLen:word):boolean;
//запись серийн. ном. в устройство открывая/закр. сеанс связи
function WriteSerialNumberOpenClose:boolean;virtual;
//чтение серийн. ном. из устройства открывая/закр. сеанс связи
function ReadSerialNumberOpenClose:boolean;virtual;
function WriteSerialNumber:boolean;virtual;
function ReadSerialNumber:boolean; virtual;
//чтение одного байта
function ReadByteFromEEprom(Addr:integer;var b:byte):boolean;virtual;abstract;
//запись одного байта
function WriteByteToEEprom(Addr:integer; b:byte):boolean;virtual;abstract;
TThisDevice
function ReadSerialNumber:boolean; override;
function WriteSerialNumber:boolean;override;
function ReadByteFromEEprom(Addr:integer;var b:byte):boolean;override;
function WriteByteToEEprom(Addr:integer; b:byte):boolean;override;
Порядок выолнения чтения
TAnyDevice .ReadSerialNumberOpenClose
TThisDevice.ReadSerialNumber
TAnyDevice .ReadDataFromEEprom
TThisDevice.ReadByteFromEEprom
Запись
TAnyDevice .WriteSerialNumberOpenClose
TThisDevice.WriteSerialNumber
TAnyDevice.WriteDataFromEEprom
TThisDevice.WriteByteFromEEprom <<--!!!! здесь баг
в теле TAnyDevice.WriteDataFromEEprom при попытке вызвать
WriteDataFromEEprom Access Violation.
nastya (2005-09-22 16:25:00) [21][17] ну это понятно
nastya (2005-09-22 16:24:00) [22][15]
function TAnyDevice.WriteDataToEEprom(Addr:integer; PData:PByteArray;DataLen:word):boolean;
var
i,a:integer;
b:word;
Begin
result:=true;
b:=0;
if DataLen<=0 then
exit;
repeat
a:=Addr+b;
result:=result and WriteByteToEEprom(a,PData[b]);
b:=b+1;
until (not result) or (b>DataLen-1);
End;
Выдает:
Project.... raised exception EAccessViolation with message 'Access violation at adress 00481F13 in module... Read of adress 0000001C'.
Причем выдает при пошаговой отладке именно в этот момент -при попытке выполнить WriteByteToEEprom. Для отладки же пыталась строчкой раньше посмотреть self.ClassName - накрывается тогда здесь.
umbra (2005-09-22 16:13:00) [23]
> umbra
> пусть он будет пустой
прошу прощения, не надо делать пустым. это ж функция
nastya (2005-09-22 16:13:00) [24][13]
TAnyMeter=TAnyDevice -это я для простоты :)
Digitman (2005-09-22 16:13:00) [25]так...
базар по поводу виртуальности/абстрактности/наследования м.б. долгим и бесплодным - книга даст ВМСЕ ответы, ибо она - источник знаний.
поехали назад, к отправной точке сабжа, обладающей НЕОПОРОВЕРЖИМЫМИ конкретностями
цитирую :
> а при записи Acsess Violation
приведи дословно сообщение об исключении, конкретную строчку кода конкретного метода конкретного класса, при выполнении которой было возбуждено данное исключение
nastya (2005-09-22 16:03:00) [26][13] попробую
просто на мой взгляд все должно работать нормально и так, то есть если я правильно понимаю, абстрактиные методы примерно для такого использования и преднозначены :)
nastya (2005-09-22 16:00:00) [27][10]
Еще раз. Сначала.
1)Device:=TThisDevice.Create
2)Device.WriteSerialNumberOpenClose (реально этот метод в TAnyDevice)
function TAnyMeter.WriteSerialNumberOpenClose:boolean;
Begin
result:=false;
if not HardOpenSession then exit;
result:=WriteSerialNumber; // Здесь переопределено в TThisDevice
CloseSession;
End;
function TThisDevice.WriteSerialNumber:boolean;
var
Dat:array[1..128] of byte;
Addr:word;
Len:byte;
Begin
result:=false;
здесь готовлю данные
if not WriteDataToEEprom(Addr,@Dat[1],Len) then //здесь реально TAnyDevice
begin
обработка ошибки
exit;
end;
result:=true;
End;
umbra (2005-09-22 15:55:00) [28]А вы этот метод сделайте не абстрактным, а просто виртуальным, а в имплементации пусть он будет пустой или просто возвращает true
nastya (2005-09-22 15:50:00) [29][7]
так реальный - то объект TThisDevice
Digitman (2005-09-22 15:49:00) [30]э-э-э .. скорей я торможу) ...
тогда объясни мне, тундре, накой ляд ты сначала вызываешь Предок.WriteDataToEEprom, а следом Наследник.WriteByteToEEprom, если Предок при исполнении перекрытого в Наследнике WriteDataToEEprom и так уже вызывает тот самый WriteByteToEEprom ?
nastya (2005-09-22 15:43:00) [31][6]
Торможу?? :)
function TAnyDevice.Write DataToEEprom(Addr:integer; PData:PByteArray;DataLen:word):boolean;
var
i,a:integer;
b:word;
Begin
result:=true;
b:=0;
if DataLen<=0 then
exit;
repeat
a:=Addr+b;
result:=result and Write ByteToEEprom(a,PData[b]);
b:=b+1;
until (not result) or (b>DataLen-1);
End;
Digitman (2005-09-22 15:41:00) [32]
> nastya
приводи уже РЕАЛЬНЫЙ код ... иначе - базар-вокзал ...
umbra (2005-09-22 15:40:00) [33]
> в теле TAnyDevice.WriteDataToEEprom по количеству байт вызывается
> WriteByteToEEprom перекрытый в классе TThisDevice
Так вызывается ж в том классе, где он абстрактный! Его там как бы и нет вовсе, название одно! А можно его вызывать только там, где он перекрыт, т.е в TThisDevice, да и то это будет не TAnyDevice.WriteByteToEEprom, а TThisDevice.WriteByteToEEprom, о котором TAnyDevice ничего не знает.
Digitman (2005-09-22 15:38:00) [34]
> так я дважы и не вызызваю
здрасть-приехали !
а ЭТО что ?
TAnyDevice.WriteDataFromEEprom
TThisDevice.WriteByteFromEEprom<<--!!!! здесь баг
используется один и тот же, судя по всему, объект..
nastya (2005-09-22 15:37:00) [35][1]
> Т.е. их можно вызывать только в классе-наследнике,где они
> реализованы. В TAnyDevice WriteByteFromEEprom вызывать нельзя
А как еще тогда?
Идеология записи мноджества байт общая -пишем их по одному в цикле. То есть это метод уровня TAnyDevice. А как конкретно этот байт закинуть знает только реальное устройство.
nastya (2005-09-22 15:34:00) [36][2]
так я дважы и не вызызваю
в теле TAnyDevice.WriteDataToEEprom по количеству байт вызывается
WriteByteToEEprom перекрытый в классе TThisDevice
umbra (2005-09-22 15:30:00) [37]Из хелпа про абстрактные методы:
You can call an abstract method only in a class or instance of a class in which the method has been overridden.
Т.е. их можно вызывать только в классе-наследнике,где они реализованы. В TAnyDevice WriteByteFromEEprom вызывать нельзя
Arm79 (2005-09-22 15:30:00) [38]а все таки исходники то не мешало бы...
Digitman (2005-09-22 15:30:00) [39]
> TAnyDevice.WriteDataFromEEprom
> TThisDevice.WriteByteFromEEprom<<--!!!! здесь баг
ЗАЧЕМ ДВАЖДЫ вызывать метод WriteByteFromEEprom() ОДНОГО И ТОГО ЖЕ объекта ?
ведь поскольку этот метод у класса-предка является виртуальным и он перекрыт в классе-потомке, то при первый же вызов - это вызов метода TThisDevice.WriteByteFromEEprom !
?