Форум: "Основная";
Текущий архив: 2004.05.30;
Скачать: [xml.tar.bz2];
Внизprocedure of class? Найти похожие ветки
← →
Sandman25 (2004-05-20 10:38) [0]Доброе время суток.
Подскажите, пожалуйста, как можно заменить объявление
Type
TEntityProcedure = procedure (...) of object
чтобы использовать не обычные методы, а "классовые"
class procedure (...)
EntityClassFor(CashData).CallProcAndKeepContext(EntityProcedureFor(CashData), ...)
EntityClassFor возвращает TEntityClass = class of TEntity
EntityProcedureFor возвращает TEntityProcedure
Внутри CallProcAndKeepContext происходит использование "классовых" методов для сохранения/восстановления контекста и между ними вызывается процедура, передаваемая параметром.
Спасибо.
← →
Sandman25+1 (2004-05-20 10:44) [1]Только что проверил в тестовом приложении... Вроде бы никакой разницы нет. Вопрос снимается.
Хотя в реальном приложении access violation происходит именно при вызове метода, переданного параметром и параметр вроде правильный. Буду разбираться.
← →
Тимохов © (2004-05-20 10:45) [2]вообще говоря, это прекрасно работает.
в чем проблема?type
TCls = class
class procedure a;
end;
TProc = procedure of object;
class
procedure TCls.a;
begin
showmessage("a");
end;
procedure TForm1.Button2Click(Sender: TObject);
var
kProc: TProc;
begin
kProc := TCls.a;
kProc(); // display "a"
end;
← →
Sandman25+1 (2004-05-20 11:10) [3]Проблема действительно есть. Что-то я неправильно делаю, видимо.
type
TCashData = (cdMotiveType
//, ...
);
TEntityRecord = record
EntityClass: TEntityClass;
EntityProcedure: TEntityProcedure;
end;
const
EntityArr: array[TCashData] of TEntityRecord =
(
// cdMotiveType,
(EntityClass: TFormularEntity; EntityProcedure: TFormularEntity.Filter)
//, ...
)
function EntityClassFor(CashData: TCashData): TEntityClass;
begin
Result := EntityArr[CashData].EntityClass;
end;
function EntityProcedureFor(CashData: TCashData): TEntityProcedure;
begin
Result := EntityArr[CashData].EntityProcedure;
end;
class procedure TEntity.CallProcAndKeepContext(
EntityProcedure: TEntityProcedure;
FormatDataAdapter: TFormatDataAdapter);
var
OldFilterArr: array of String;
Index: Integer;
begin
SetLength(OldFilterArr, GetDataSetCount);
for Index := Low(OldFilterArr) to High(OldFilterArr) do
OldFilterArr[Index] := TDataSetAdapter.GetOldFilterAndDisableControls(GetDataSet(FormatDataAdapter, Index));
try
EntityProcedure(FormatDataAdapter);
finally
for Index := Low(OldFilterArr) to High(OldFilterArr) do
TDataSetAdapter.SetOldFilterAndEnableControls(GetDataSet(FormatDataAdapter, Index), OldFilterArr[Index]);
end;
end;
Так вот при вызове
EntityClassFor(CashData).CallProcAndKeepContext(EntityProcedureFor(CashData), FormatDataAdapter);
Я попадаю в TFormularEntity.CallProcAndKeepContext, как и ожидается.
Но в Watch я вижу:
EntityArr[cdmotivetype],r: (EntityClass:TEntityClass($1BB10F0); EntityProcedure:$1BB10A4)
@entityprocedure: $1BB10F0
@tformularentity.filter: $1BB1B74
@tentity.filter: $1BB1B74
Получается, что параметр EntityProcedure указывает не на Tformularentity.filter, а на Tformularentity. Соответственно при вызове
EntityProcedure(FormatDataAdapter) я получаю Access Violation, даже не заходя в TformularEntity.Filter.
Сообщение Write of address 01BB10B4.
Может, нужно инициализировать массив только в run-time?
← →
Sandman25+1 (2004-05-20 11:18) [4]Проблема похоже есть, причем в моем коде.
type
TCashData = (cdMotiveType {, ...});
type
TEntityRecord = record
EntityClass: TEntityClass;
EntityProcedure: TEntityProcedure;
end;
const
EntityArr: array[TCashData] of TEntityRecord =
(
// формуляр
// cdMotiveType,
(EntityClass: TFormularEntity; EntityProcedure: TFormularEntity.Filter) {,...}
);
function EntityClassFor(CashData: TCashData): TEntityClass;
begin
Result := EntityArr[CashData].EntityClass;
end;
function EntityProcedureFor(CashData: TCashData): TEntityProcedure;
begin
Result := EntityArr[CashData].EntityProcedure;
end;
class procedure TEntity.CallProcAndKeepContext(
EntityProcedure: TEntityProcedure;
FormatDataAdapter: TFormatDataAdapter);
var
OldFilterArr: array of String;
Index: Integer;
begin
SetLength(OldFilterArr, GetDataSetCount);
for Index := Low(OldFilterArr) to High(OldFilterArr) do
OldFilterArr[Index] := TDataSetAdapter.GetOldFilterAndDisableControls(GetDataSet(FormatDataAdapter, Index));
try
EntityProcedure(FormatDataAdapter);
finally
for Index := Low(OldFilterArr) to High(OldFilterArr) do
TDataSetAdapter.SetOldFilterAndEnableControls(GetDataSet(FormatDataAdapter, Index), OldFilterArr[Index]);
end;
end;
Так вот при вызове
EntityClassFor(cdMotiveType).CallProcAndKeepContext(EntityProcedureFor(cdMotiveType),
я попадаю, как и ожидается в TformularEntity.CallProcAndKeepContext, но в Watch вижу странные вещи:
entityarr[cdmotivetype],r: (EntityClass:TEntityClass($1BB10F0); EntityProcedure:$1BB10A4)
@entityprocedure: $1BB10F0
@tformularentity.filter: $1BB1B74
То есть локальный параметр EntityProcedure <> entityarr[cdmotivetype].EntityProcedure
И потом получаю AV: write of address 01BB10B4
Может, нужно явно инициализировать массив, а не использовать const?
← →
Sandman25+1 (2004-05-20 11:27) [5]Все, решил :) Сделал инициализацию массива в initialization-секции и проблема исчезла. Const массив почему-то "дурковал" :(
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.05.30;
Скачать: [xml.tar.bz2];
Память: 0.46 MB
Время: 0.031 c