リストを保持するクラスをリスト化するには?

解決


  2005-01-18 09:29:11  No: 12770

動的に確保した構造体を保持するためのTListを複数含むクラスを、さらにTListを含んだクラスにてリスト状にしようとしています。
その際、クラスに保持されている内部のTListの値を読み取る、または書き込む動作を、TListを含んだクラスのメソッドに持たせようとするために、TListのCountメソッドを呼び出して試みているのですが「EAccessViolation クラスの例外を生成しました」と出て止まってしまいます。

イメージとしては以下のような感じです。
-------------------------------------------------------------------------------------
TMyClass1 = class                    //このクラスをリスト状にして保持したい
  private
    MyList1:TList;  MyList2:TList;   //それぞれ構造体の変数が保持されている     
    procedure …;
  (以下略)

TMyClass2 = class                    //このクラス内のTListがTMyClass1をリスト上に保持
  private
    MyList3:TList;                   //このリスト内にTMyClass1が入る

例えばTList2のCountメソッドにアクセスするには、
for i:=0 to MyList3.Count-1 do begin
  for j:=0 to TMyClass1(MyList3.Items[j]).MyList2.Count-1 do begin
                               (↑このメソッドでエラーを吐く模様)
    …
-------------------------------------------------------------------------------------
という具合です。このように扱うのが正しいのか良くわからないのですが、正しい方法や、または根本的に正しい使い方があれば、ご教授お願いいたします。


  2005-01-18 09:35:36  No: 12771

肝心なところを省略したのでは、エラーの原因がわかりません。

TMyClass1 = class    
のCreate ,destroyで  
MyList1 :=TList.Create;
MyList1.free
してます?

基本です。

以上

暇だから  あとで、作ってあげよう


  2005-01-18 10:11:13  No: 12772

好みで修正してください。
Add,Delete,Clearとかカスタマイズはご自分でどうぞ。
眠くなったので、作りかけで途中ですが寝ます。
間違いなどは自分で修正してください
あとはご自分でいろいろ試行錯誤してください。
では、

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
TMyClass1 = class
  private
    MyList1:TList;
    MyList2:TList;
  public
    { Public 宣言 }
    constructor Create;
    destructor Destroy; override;
  end;

type
TMyClass2 = class
  private
    MyList3 : TList;   //このリスト内にTMyClass1が入る
    function GetMyItem(Index: Integer): TMyClass1;
  public
    { Public 宣言 }
    property MyItems[Index: Integer]: TMyClass1 read GetMyItem;
    constructor Create;
    destructor Destroy; override;
  end;

constructor TMyClass1.Create;
begin
  inherited  Create;
  MyList1 := TList.Create;
  MyList2 := TList.Create;
end;

destructor TMyClass1.Destroy;
begin
  // MyList2 のdata保持内容をFreeするメソッドを書く
  // MyList1  ”
  MyList2.Free;
  MyList1.Free;
  inherited Destroy;
end;

//////////////////////////

function TMyClass2.GetMyItem(Index: Integer): TMyClass1;
begin
  Result := TMyClass1(MyList3.Items[Index])
end;

constructor TMyClass2.Create;
begin
  inherited  Create;
  MyList3 := TList.Create;
end;

destructor TMyClass2.Destroy;
  var i: integer;
begin
  for i := MyList3.Count-1 downto 0 do
    TMyClass1(MyList3.Items[i]).Free;
  MyList3.Free;
  inherited Destroy;
end;

var Mylist : TMyClass2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Mylist := TMyClass2.Create;

  // データ一個追加
  Mylist.MyList3.add(TMyClass1.Create);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Mylist.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.Lines.add(IntToStr(Mylist.MyList3.Count));
  Memo1.Lines.add(IntToStr(Mylist.MyItems[0].MyList1.Count));
  Memo1.Lines.add(IntToStr(Mylist.MyItems[0].MyList2.Count));
   Mylist.MyItems[0].MyList2.add(nil);
   Mylist.MyItems[0].MyList2.add(nil);
  Memo1.Lines.add(IntToStr(Mylist.MyItems[0].MyList2.Count));
end;

end.


  2005-01-18 10:18:33  No: 12773

あっ

>例えばTList2のCountメソッドにアクセスするには、
>for i:=0 to MyList3.Count-1 do begin
>  for j:=0 to TMyClass1(MyList3.Items[j]).MyList2.Count-1 do begin
>                               (↑このメソッドでエラーを吐く模様)
あなた、iとj代入間違ってますよ。
MyList3.Items[j]  →    MyList3.Items[i]


  2005-01-18 21:57:11  No: 12774

。さん、ご返答ありがとうございます。
例文で上げたソースですが、
>あなた、iとj代入間違ってますよ。
>MyList3.Items[j]  →    MyList3.Items[i]
この文は、実際には正しく書けております。
ちなみにCreateやらFreeなども書いてませんでしたがやっております。
紛らわしい書き方やミスをして申し訳ございませんでした。

。さんの返事を受けまして、上記のプログラムを改変して動くようにしたものと、自己のプログラムとを追っていった結果、どうやらオブジェクトの開放部分で不具合が生じていたようです。
お手を煩わせてしまい申し訳ございませんでした。心からお礼を申し上げます。
ありがとうございました。

-----------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Controls, Forms, StdCtrls;

type
  PZahyo=^TZahyo;
  TZahyo=Record
    x,y:Integer;
  end;

type
TMyClass1 = class
  private
    MyList1:TList;
  public
    { Public 宣言 }
    constructor Create;
    destructor Destroy; override;
  end;

type
TMyClass2 = class
  private
    MyList3 : TList;   //このリスト内にTMyClass1が入る
    function GetMyItem(Index: Integer): TMyClass1;
  public
    { Public 宣言 }
    property MyItems[Index: Integer]: TMyClass1 read GetMyItem;
    constructor Create;
    destructor Destroy; override;
  end;

//////////////////////////
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
    MyList:TMyClass2;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TMyClass1.Create;
begin
  inherited  Create;
  MyList1 := TList.Create;
end;

destructor TMyClass1.Destroy;
var i:Integer;
begin
  for i := MyList1.Count-1 downto 0 do
    Dispose(PZahyo(MyList1[i]));
  MyList1.Free;
  inherited Destroy;
end;

////////////////////////
function TMyClass2.GetMyItem(Index: Integer): TMyClass1;
begin
  Result:=TMyClass1(MyList3.Items[Index])
end;

constructor TMyClass2.Create;
begin
  inherited  Create;
  MyList3 := TList.Create;
end;

destructor TMyClass2.Destroy;
  var i: integer;
begin
  for i := MyList3.Count-1 downto 0 do
    TMyClass1(MyList3.Items[i]).Free;
  MyList3.Free;
  inherited Destroy;
end;

//////////////////////////
procedure TForm1.Button1Click(Sender: TObject);
var i,j:Integer;
    temp:PZahyo;
begin
  Memo1.Lines.Clear;
  for i:=0 to Mylist.MyList3.Count-1 do begin
    for j:=0 to TMyClass1(Mylist.MyList3.Items[i]).MyList1.Count-1 do begin
      temp:=TMyClass1(Mylist.MyList3.Items[i]).MyList1.Items[j];
      Memo1.Lines.add(inttostr(i)+','+inttostr(j)+': (x,y) = ('+inttostr(temp.x)+','+inttostr(temp.y)+')');
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyList:=TMyClass2.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Mylist.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var pNewSpot:PZahyo;
    i:Integer;
    temp1:TMyclass1;
begin
  Randomize;
  temp1:=TMyClass1.Create;
  for i:=0 to 9 do begin
    new(pNewSpot);
    pNewSpot.x:=Trunc(Random(100));
    pNewSpot.y:=Trunc(Random(100));
    TMyclass1(temp1).MyList1.Add(pNewSpot);
  end;
  Mylist.MyList3.Add(temp1);
end;

end.
-----------------------------------------------------------------------
ちなみに改変したものは以上のような形になりました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加