In Object Pascal, all objects are created in the heap space of memory rather than on the stack, so the constructor will not be automatically called by the compiler like C++. Constructing objects and destructing objects are the responsibility of the programmer.
To construct an object, you must first allocate memory for the object. This step is supported by the compiler in Object Pascal - the so-called "Compiler Magic" Magic)", the programmer does not need to participate in this process; then the data members of the object must be initialized, and the compiler will be responsible for "clearing" them, but if there is a special assignment, it can be completed in the constructor; when the object is destructed The requested resources (not the memory occupied by the object itself) need to be released. These tasks are the responsibility of the destructor; the recycling of the memory occupied by the object itself is also completed by "compiler magic".
Allocation and recycling of object memory
When the compiler allocates memory for an object, the support it provides is to insert these lines of assembly code before calling the constructor:
test dl, dl
jz +$08
add esp, -$10
call @ClassCreate // Pay attention to this line of code
The last line of the above code calls the _ClassCreate function on line 8949 of the system.pas file (subject to Delphi 6). This function specifically allocates appropriate memory for each object. After the memory allocation is completed, the constructor of the class is called to initialize the data members. Afterwards, the compiler will insert the following lines of assembly code:
test dl, dl
jz +$0f
call @AfterConstruction
pop dWord ptr fs:[$00000000]
add esp, $0c
The main job is to call AfterConstruction of each object instance. This call is of no use in Delphi. Its existence is reserved for C++Builder.
Similarly, when destructing an object, the destructor of the class must first be called to release the resources requested by the object. After that, the memory space occupied by the object itself is recycled. This work is completed by the compiler inserting the following assembly code after calling the destructor:
call @BeforeDestruction
test dl, dl
jle +$05
call @ClassDestroy
The work done by these codes corresponds to what is done when constructing the object and allocating memory, mainly calling the _ClassDestroy function on line 8997 in system.pas.
Constructor and destructor
To define a constructor, use the Constructor keyword. By convention, the name of the constructor is Create (of course other names can be used, but that is by no means a good design!). like:
type
TMyFamily = class // The class defined for your family
PRivate
FMyFatherName : String; // your father's name
FMyMotherName : String; // your mother's name
… // Other members of your family
Public
Constructor Create(strFatherName, strMotherName : String);
…… // Other methods
End;
You may ask, if I do not provide a constructor for my class, can its objects be created? The answer is: yes. The reason has been mentioned before, the allocation of the memory occupied by the object itself is completed by the compiler. And since in Object Pascal, all classes (except the TObject class itself) are derived from the TObject class, the compiler will call the TObject.Create() constructor, but this function is an empty function, and it will not affect the TMyFamily class. When the data members (FMyFatherName, FMyMotherName) are initialized, they will be automatically cleared to empty strings (i.e. ''), because TObject.Create() does not know your father or mother at all!
When creating an object, the constructor is called directly, in the following form:
MyFamilyObject := TMyFamily.Create('Zhang', 'Li');
To define a destructor, use the Destructor keyword. By convention, the destructor is named Destroy. like:
type
TMyClass = class
Public
Destructor Destroy(); override;
End;
The reason why the override statement is added at the end of the destructor declaration is to ensure that the object can be destructed correctly in the case of polymorphism (polymorphism will be discussed in detail in Section 2.4). If you do not add the override keyword, the compiler will give a warning similar to "Method 'Destroy' hides virtual method of base type 'TObject'". The warning means that the Destroy you defined hides the virtual method TObject.Destroy() of the base class. In that case, the object cannot be destructed correctly in polymorphic situations.
Note: Destructors need to be declared with an override statement.
Likewise, if there are no special resources that need to be released in your class, you don't need to define a destructor. However, when destructing an object, you should call the object's Free() method instead of calling Destroy() directly.
MyFamilyObject.Free();
This is because the Free() method will determine whether the object itself is nil, and if it is not nil, the object's Destroy() will be called to increase safety. Now that there are safer ways to do this, there's certainly no reason not to do it.
Note: Never call Destroy() directly on an object, but Free() instead.
It can be concluded from this that in Object Pascal you only need to pay attention to the allocation and release of the resources applied for by the object, and do not have to care about the space occupied by the object itself!