오브젝트 파스칼에서는 모든 객체가 스택이 아닌 메모리의 힙 공간에 생성되므로 C++처럼 컴파일러에서 생성자를 자동으로 호출하지 않습니다. 객체를 생성하고 객체를 파괴하는 것은 프로그래머의 책임입니다.
객체를 생성하려면 먼저 객체에 대한 메모리를 할당해야 합니다. 이 단계는 소위 "컴파일러 매직"이라고 불리는 오브젝트 파스칼의 컴파일러에서 지원됩니다. Magic)", 프로그래머는 이 프로세스에 참여할 필요가 없습니다. 그런 다음 개체의 데이터 멤버를 초기화해야 하며 컴파일러는 이를 "삭제"할 책임이 있지만 특별한 할당이 있는 경우 완료할 수 있습니다. 객체가 소멸될 때 요청된 리소스(객체 자체가 차지하는 메모리가 아님)는 소멸자의 책임입니다. 객체 자체가 차지하는 메모리의 재활용도 완료됩니다. "컴파일러 마법".
객체 메모리 할당 및 재활용
컴파일러가 객체에 메모리를 할당할 때 제공되는 지원은 생성자를 호출하기 전에 다음 어셈블리 코드 줄을 삽입하는 것입니다.
dl, dl 테스트
jz +$08
ESP 추가, -$10
@ClassCreate 호출 // 이 코드 줄에 주의하세요.
위 코드의 마지막 줄은 system.pas 파일의 8949번 줄에서 _ClassCreate 함수를 호출합니다(Delphi 6에 따라 다름). 이 함수는 각 개체에 대해 적절한 메모리를 구체적으로 할당합니다. 메모리 할당이 완료된 후 클래스 생성자가 호출되어 데이터 멤버를 초기화합니다. 그 후에 컴파일러는 다음 어셈블리 코드 줄을 삽입합니다.
dl, dl 테스트
jz +$0f
@AfterConstruction에 전화하세요
팝 dWord ptr fs:[$00000000]
esp 추가, $0c
주요 작업은 각 개체 인스턴스의 AfterConstruction을 호출하는 것입니다. 이 호출은 C++Builder용으로 예약되어 있습니다.
마찬가지로, 객체를 소멸시킬 때 클래스의 소멸자를 먼저 호출하여 객체가 요청한 리소스를 해제해야 합니다. 그 후, 객체 자체가 차지하는 메모리 공간은 소멸자를 호출한 후 컴파일러가 다음 어셈블리 코드를 삽입하여 완료됩니다.
@BeforeDestruction으로 전화하세요
테스트 DL, DL
jle +$05
@ClassDestroy로 전화하세요
이러한 코드에 의해 수행되는 작업은 주로 system.pas의 8997행에서 _ClassDestroy 함수를 호출하여 객체를 구성하고 메모리를 할당할 때 수행되는 작업에 해당합니다.
생성자와 소멸자
생성자를 정의하려면 Constructor 키워드를 사용합니다. 일반적으로 생성자의 이름은 Create입니다(물론 다른 이름을 사용할 수도 있지만 이는 결코 좋은 디자인이 아닙니다!). 좋다:
유형
TMyFamily = class // 가족에 대해 정의된 클래스
사적인
FMyFatherName : String // 아버지의 이름;
FMyMotherName : String // 어머니의 이름;
… // 다른 가족 구성원
공공의
생성자 Create(strFatherName, strMotherName : String);
…… // 다른 방법
끝;
내 클래스에 생성자를 제공하지 않으면 해당 객체를 만들 수 있는지 물어볼 수 있습니다. 대답은 다음과 같습니다. 그렇습니다. 그 이유는 앞서 언급했듯이, 객체 자체가 차지하는 메모리 할당은 컴파일러에 의해 완료됩니다. 그리고 오브젝트 파스칼에서는 모든 클래스(TObject 클래스 자체 제외)가 TObject 클래스에서 파생되므로 컴파일러는 TObject.Create() 생성자를 호출하지만 이 함수는 빈 함수이므로 TMyFamily 클래스에 영향을 주지 않습니다. 데이터 멤버(FMyFatherName, FMyMotherName)가 초기화되면 TObject.Create()가 아버지나 어머니를 전혀 모르기 때문에 자동으로 빈 문자열(예: '')로 지워집니다.
객체를 생성할 때 생성자는 다음 형식으로 직접 호출됩니다.
MyFamilyObject := TMyFamily.Create('장', '리');
소멸자를 정의하려면 Destructor 키워드를 사용합니다. 규칙에 따라 소멸자의 이름은 Destroy입니다. 좋다:
유형
TMyClass = 클래스
공공의
소멸자 파괴();
끝;
소멸자 선언 끝에 override 문을 추가하는 이유는 다형성의 경우 객체가 올바르게 소멸될 수 있도록 하기 위한 것입니다(다형성에 대해서는 섹션 2.4에서 자세히 설명합니다). override 키워드를 추가하지 않으면 컴파일러는 "'Destroy' 메서드가 기본 유형 'TObject'의 가상 메서드를 숨깁니다"와 유사한 경고를 표시합니다. 경고는 정의한 Destroy가 기본 클래스의 가상 메소드 TObject.Destroy()를 숨긴다는 의미입니다. 이 경우 객체는 다형성 상황에서 올바르게 소멸될 수 없습니다.
참고: 소멸자는 재정의 문을 사용하여 선언해야 합니다.
마찬가지로, 클래스에서 해제해야 하는 특별한 리소스가 없으면 소멸자를 정의할 필요가 없습니다. 그러나 객체를 소멸시킬 때는 Destroy()를 직접 호출하는 대신 객체의 Free() 메서드를 호출해야 합니다.
MyFamilyObject.Free();
이는 Free() 메소드가 객체 자체가 nil인지 판단하고, nil이 아닌 경우 안전성을 높이기 위해 객체의 Destroy()를 호출하기 때문입니다. 이제 이 작업을 수행하는 더 안전한 방법이 있으므로 수행하지 않을 이유가 없습니다.
참고: 개체에 대해 Destroy()를 직접 호출하지 말고 대신 Free()를 호출하세요.
이를 통해 오브젝트 파스칼에서는 객체가 적용한 리소스의 할당 및 해제에만 주의하면 되고 객체 자체가 차지하는 공간에는 신경 쓸 필요가 없다는 결론을 내릴 수 있습니다.