2014-02-16 2 views
-1

내 프로그램에서 클래스를 사용하려고합니다.클래스의 멤버 변수를 편집 할 때 오류가 발생했습니다.

TStack = Class 
Public 
    constructor Create; Overload; 
    Procedure Add(Frm:TForm); 
    Procedure Remove(); 
    Procedure Do_Close; 

Private 
    List : Array[1..Max_Forms] of Rec; 
    Count : Byte; 
End; 

생성자 :

constructor TStack.Create; 
begin 
    Self.Count := 0; 
end; 

Procedure TStack.Add(Frm:TForm); 
begin 
    Inc(Self.Count); 
    List[Count].Form  := @Frm; 
    List[Count].Width := Frm.Width; 
    List[Count].Height := Frm.Height; 
    List[Count].left  := Frm.Left; 
    List[Count].Top  := Frm.Top; 
end; 

나는 카운트 변수의 값을 변경할 수 없습니다! 런타임 오류가 발생합니다 : 액세스 위반 .... 주소 000001E4 쓰기

무엇이 문제입니까?!

Rec = Record 
     Form  : ^TForm; 
     Maximized : Boolean; 
     Width, 
     Height, 
     left, 
     Top  : Integer; 
    End; 

그리고

Procedure TStack.Do_Close; 
var 
    i  : integer; 
    MyForm : TForm; 
begin 
i := .....some code here.......; 
MyForm := @List[i].Form; 
ShowMessage('I will close '+MyForm.Caption); 
MyForm.Close; 
end; 

과 같이 생성자를 호출 :이 같은 구조는 각 양식에 대한 포인터를 저장하기 위해 노력하고있어

을 자세한 내용

'Count'를 초기화하는 방법 :

Stack.Create; 
+0

생성자의 행 또는 추가의 행 중 어떤 행이 충돌합니까? – Blorgbeard

+0

많은 문제가 있습니다. 아마 당신을 아프게하는 것은 당신이 그 대상을 정확하게 창조하지 않았다는 것입니다. 당신은 그 코드를 보여주지 않았습니다. 제발. 바이트가 아닌 정수를 사용하십시오. 정적 배열을 사용하지 마십시오. 동적 배열 또는'TList '을 사용하십시오. 0부터 인덱스 배열. 지역 변수의 주소를 가져 가지 마십시오. –

+0

예,'Stack.create'가 작동하지 않지만'stack = Tstack.create'가 몇 가지 문제를 해결했습니다 (왜?!)! 왜 정적 배열을 사용하면 안되나요?! "지역 변수의 주소를 사용하지 마십시오"라는 것은 무엇을 의미합니까! 고마워요 :) – Jessica

답변

4

의견에 설명한 바와 같이이 같은 객체를 생성하려고 :

var 
    Stack: TStack; 
.... 
Stack.Create; 

이것은 고전적인 실수, 우리는 모든했습니다 하나입니다. 초기화되지 않은 인스턴스 변수에서 메소드를 호출하고 있습니다. 당신이 작성해야하는 클래스의 인스턴스를하기 위해

: 그 꼭대기에

Stack := TStack.Create; 

을 나는 다음과 같은 의견을 가지고 배열

  1. 사용 제로 기반 색인. 그것은 시대 착오적 인 끈을 제외하고는 델파이의 모든 곳에서 행해지는 대회입니다. 그리고 심지어 그것은 최신 버전에서 변화하고 있습니다.
  2. 정당한 이유가없는 한 스택에 정적 배열을 사용하지 마십시오. 공간이 부족할 위험이 있습니다. 또는 필요한 것보다 많은 메모리를 할당하십시오. 동적 배열을 사용하십시오.
  3. 동적 배열 대신 TList<T>을 사용할 수 있습니다.
  4. 그럼에도 불구하고 완벽한 스택 클래스를 만드는 이유가 무엇인지 궁금합니다. TStack<T>.
  5. 스택에 로컬 변수의 주소를 저장합니다. TStack.Add에서 @Frm을 컨테이너에 추가합니다. TStack.Add이 반환 되 자마자 @Frm은 의미가 없습니다. Frm은 소유하고있는 함수가 반환 될 때 수명이 끝나는 지역 변수이기 때문입니다. 나는 Frm 사본을 갖고 싶어한다고 생각합니다. 더 자세히 항목 5를 따기

는 귀하의 기록은 다음과 같이 선언한다 :

Rec = Record 
    Form  : ^TForm; 
    Maximized : Boolean; 
    Width, 
    Height, 
    left, 
    Top  : Integer; 
End; 

^TForm를 사용하는 실수입니다. 그것은 객체에 대한 포인터를 가지고있는 변수에 대한 포인터입니다. 이것은 간접 지정의 두 가지 수준입니다. 하나는 너무 많습니다. 필드를 TForm 유형으로 선언해야합니다.델파이 객체 참조 변수가 작동하는 방식을 수정하는 것이 좋습니다. 델파이 클래스는 레퍼런스 타입으로 알려져 있습니다. 유형이 TMyClass 인 변수는 TMyClassclass(...)이고 이미 포인터입니다. 언어는 . 연산자를 사용하여 멤버에 액세스 할 때 자동으로 포인터의 참조를 해제합니다.