Форум: "Основная";
Текущий архив: 2002.05.27;
Скачать: [xml.tar.bz2];
ВнизРабота с динамическим массивом объектов Найти похожие ветки
← →
Jaguar (2002-05-16 11:41) [0]Добрый утро/день/вечер/ночь Мастерам!
Делаю приблизительно так:
var List:TMonstrList;
begin
...
SetLength(List.FList, 1);
//длина нормально задается, становится равной 1
List.Flist[0]:=TMonstr.Create;
...
end;
(Для добавления в модуле есть свои процедуры, однако через них такой же результат, думал в них дело, поэтому еще так пробовал)
Вроде как создал объект, однако при дальнейшей попытке обратиться к полям этого объекта вываливается ошибка AccessViolation. Кто-нибудь может подсказать, в чем залючается кривость моих рук?
И другой вопрос: создаю отдельный экземпляр TMonstr. Присваиваю его полям какое-то значение, уничтожаю его - никаких ошибок нет. Закрываю программу - она закрывается, однако выдает сообщение Stack overflow. Почему при закрытии программы и почему вообще выдает - не могу понять.
И третий вопрос, опять же по этим структурам. К тому самому массиву FList добавляю три элемента путем таких вот действий:
SetLength(List.FList, List.Length+1);
List.Flist[List.High]:=TMonstr.Create;
После того, как создается третий объект, программа вываливается с ошибкой, которую Delphi даже не ловит. В чем тут дело - опять же не могу понять. Если кто-то сможет помочь советом - очень прошу.
(Ниже приводится полный текст модуля-описания этих самых объектов)
← →
Jaguar (2002-05-16 11:43) [1]
unit uMonstrType;
interface
uses uUtils, SysUtils;
type
TDiceType=(d4, d6, d8, d10, d12, d20, d100);
TDmgType=( dtKnife, dtBlade, dtAxe, dtMace, dtPike, dtThrow, dtShoot, dtHand,
dtFire, dtAir, dtEarth, dtWater, dtAstral, dtLife, dtDeath, dtLight, dtDark);
TMonstrAttack = record
Name: String[40];
Attack: integer;
AP: integer;
SHKU: integer;
SHKP: integer;
Range: integer;
DmgCount: integer;
DmgDice: TDiceType;
DmgBonus: integer;
DmgType: TDmgType;
end;
TMonstr = class
public
Code: integer;
Name: string; // название (используется в интерфейсе)
Description: string; // Описание
Level: integer;
Intellect: integer;
Perception: integer;
AP: integer;
MaxHits: integer;
MaxCrHits: integer;
MaxOtrHits: integer;
{
Hits: integer;
CrHits: integer;
OtrHits: integer;
{}
Defence: integer;
Armor: integer;
Exp: integer;
Attacks: array of TMonstrAttack;
private
function getAttackCount: integer;
function getAttack(index: integer): TMonstrAttack;
procedure setAttack(index: integer; const Attack: TMonstrAttack);
function Count:integer;//количество атак
public
procedure Init;
constructor Create; overload;
destructor Destroy; override;
// запись / сохранение
procedure LoadFrom(const F: file);
procedure SaveTo(const F: file);
function AddAttack: integer; // возвращает ИНДЕКС
procedure DelAttack(index: integer); // удаление по индексу
property AttackCount: integer read getAttackCount;
property AttackList[index: integer]: TMonstrAttack read getAttack write setAttack;
end;
TMonstrList = class
private
MaxCode: integer;
function getLow: integer;
function getHigh: integer;
function getLength: integer;
// возвращает индекс по коду
function getIndex(code: integer): integer;
// доступ по коду
procedure setDataByCode(code: integer; const MonstrData: TMonstr);
function getDataByCode(code: integer): TMonstr;
// доступ по индексу
procedure setData(i: integer; const MonstrData: TMonstr);
function getData(i: integer): TMonstr;
public
FList: array of TMonstr;
constructor Create;
destructor Destroy; override;
// добавляет элемент и возвращает указатель на него
function Add: TMonstr;
// удаляет элемент с указанным кодом
procedure Del(code: integer);
// проверяет наличие элемента с указанным кодом
function Exist(code: integer): boolean;
// очищает список
procedure Clear;
// запись / сохранение
procedure LoadFromFile(const F: file);
procedure SaveToFile(const F: file);
property Low: integer read getLow;
property High: integer read getHigh;
property Length: integer read getLength;
// доступ по коду
property Data[Code: integer]: TMonstr read getDataByCode write setDataByCode; default;
// доступ по индексу
property List[i: integer]: TMonstr read getData write setData;
end;
implementation
procedure TMonstr.Init;
begin
Code := 0;
Name := "Новый";
Description := "";
Attacks := nil;
Level := 1;
Intellect := 1;
Perception := 1;
MaxHits := 1;
MaxCrHits := 1;
MaxOtrHits := 1;
Defence := 0;
Armor := 0;
Exp := 0;
end;
constructor TMonstr.Create;
begin
inherited;
Init;
AddAttack;
end;
destructor TMonstr.Destroy;
begin
SetLength(Attacks, 0);
inherited;
end;
procedure TMonstr.SaveTo(const F: file);
var i, count: integer;
begin
end;
procedure TMonstr.LoadFrom(const F: file);
var i, count: integer;
begin
end;
function TMonstr.AddAttack: integer;
begin
SetLength(Attacks, Length(Attacks) + 1);
Attacks[Count].Name:="Атака №"+IntToStr(Count);
Attacks[Count].Attack:=1;
Attacks[Count].AP:=3;
Attacks[Count].SHKU:=0;
Attacks[Count].SHKP:=0;
Attacks[Count].Range:=1;
Attacks[Count].DmgCount:=1;
Attacks[Count].DmgDice:=d4;
Attacks[Count].DmgBonus:=0;
Attacks[Count].DmgType:=dtKnife;
AddAttack := High(Attacks);
end;
function TMonstr.getAttackCount: integer;
begin
getAttackCount := Length(Attacks);
end;
function TMonstr.getAttack(index: integer): TMonstrAttack;
begin
getAttack := Attacks[index];
end;
procedure TMonstr.setAttack(index: integer; const Attack:TMonstrAttack);
begin
Attacks[index]:=Attack;
end;
function TMonstr.Count:integer;
begin
Count:=Length(Attacks);
end;
← →
Jaguar (2002-05-16 11:44) [2]
constructor TMonstrList.Create;
begin
MaxCode := 0;
end;
destructor TMonstrList.Destroy;
var i: integer;
begin
inherited;
for i := Low to High do FList[i].Destroy;
FList := nil;
end;
function TMonstrList.getLow: integer;
begin
getLow := 0;
end;
function TMonstrList.getHigh: integer;
begin
getHigh := System.Length(FList)-1;
end;
function TMonstrList.getLength: integer;
begin
getLength := System.Length(FList);
end;
function TMonstrList.getIndex(code: integer): integer;
var i: integer;
begin
for i := Low to High do
if FList[i].Code = code then
begin
getIndex := i;
exit;
end;
getIndex := -1;
end;
procedure TMonstrList.setDataByCode(code: integer; const MonstrData: TMonstr);
var index: integer;
begin
index := getIndex(code);
if (index = -1) then exit;
FList[index].Create(MonstrData);
end;
function TMonstrList.getDataByCode(code: integer): TMonstr;
var index: integer;
begin
index := getIndex(code);
if (index = -1) then getDataByCode := nil
else getDataByCode := FList[index];
end;
procedure TMonstrList.setData(i: integer; const MonstrData: TMonstr);
begin
if (i < Low) or (i > High) then exit;
FList[i].Create(MonstrData);
end;
function TMonstrList.getData(i: integer): TMonstr;
begin
if (i < Low) or (i > High) then getData := nil
else getData := FList[i];
end;
function TMonstrList.Add(): TMonstr;
begin
MaxCode := MaxCode + 1;
SetLength(FList, Length + 1);
FList[High] := TMonstr.Create;
FList[High].Code := MaxCode;
FList[High].Name := "Монстр №"+IntToStr(Flist[High].Code);
Add := FList[High];
end;
end.
← →
Deus (2002-05-16 11:44) [3]может, так надо:
var List:array of TMonstrList;
← →
Coalycat (2002-05-16 13:09) [4]По-моему для хранения объектов лучше использовать TList
← →
softland (2002-05-16 13:27) [5]Полагаю надо перейти от использования
FList: array of TMonstr;
к использованию списка TList отнаследовав от него свой класс и переопределив методы Get и Put для работы с TMonstr.
Можно воспользоваться TStringList и его полем Objects - это удобней поскольку содержимое поля Strings может служить средством идентификации и поиска по списку.
Примерно так:
* Класс для хранения одного поля заголовка LAS файла
При разборе секции ~WELL парсим каждую линию и в сохраняем результат в
объекте данного класса. *)
THeaderRec = class (TObject)
public
//имя поля
id : string;
//ед измерения
aUnit : string;
//значение
value : string;
//коментарий
comment : string;
//возвращает значение как реальное число
function asFloat : double;
//возвращает значение как текст
function asString : string;
end;
(* Класс для хранения строк заголовка LAS файла
в Strings храним идентификатор поля: STRT, API, и тд.
в поле Object заносим объекты класса THeaderRec *)
TLASHeaderList = class(TStringList)
public
// Вызывает конструктор предшественика
constructor Create;
// Вызывает деструктор предшественика
destructor Destroy; override;
// Добавляет параметр с именем name ед. измерения _aUnit и значением value
function AddItem(const name, _aUnit, value : string ): integer;
// Возвращает ед. измерения данного параметра в виде строки}
function GetUnit(const index : string) : string;
// Устанавливает ед. измер параметра}
procedure SetUnit(const index : string; const strUnit : string);
// Возвращает значение параметра с именем index в виде строки}
function GetValue(const index : string) : string;
// Возвращает значение параметра с именем index в виде строки}
function asString(const index : string) : string;
// Возвращает значение параметра с именем index в виде числа}
function asFloat(const index : string) : double;
// Возвращает значение параметра с именем index в виде даты}
function asDateTime(const index : string) : TDateTime;
// Устанавливает значение параметра с именем index равным переданной строке}
procedure SetValue(const index : string; const strValue : string);
// Устанавливает значение параметра с именем index равным переданному числу}
procedure SetValueAsFloat(const index : string; aValue : double);
// Возвращает значение коментария к параметру с именем index в виде строки}
function GetComment(const index : string) : string;
// Устанавливает коментарий к параметру с именем index равным переданной строке}
procedure SetComment(const index : string; const strComment : string);
end;
Ясный пень вместо index : string можно использовать index : integer;
← →
softland (2002-05-16 13:30) [6]Я предлогаю перейти на списки именно из-за резкого уменьшения ошибок по выделению, освобождению памяти, а твои проблемы на 99% именно в этом. А чтобы найти их придется медленно и мучительно отлаживать твой код :(
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.05.27;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.005 c