Acerca de la asignación y el reciclaje de memoria de objetos
No sé si alguien tiene alguna idea sobre cómo colocar el registro dl aquí. Si no, piénselo. Si lo piensa, estará bien. De hecho, antes del siguiente código (1), hay una línea de código MOV dl, 1, entonces, ¿por qué es así? La razón no es muy simple: la reutilización del código. Con respecto al uso del registro dl aquí, hay una introducción en la ayuda de Delphi. Tenga paciencia y búsquelo usted mismo. Si lo encuentra, será un maestro. Esto es aprender, no, aprender a pescar, no pedir pescado. Borland dijo esto: "Utilizo el registro dl para almacenar una bandera. Si el valor es 1, crearé el objeto. De lo contrario, no crearé el objeto. Si está un poco confuso, piénselo de nuevo". de nuevo. Si aún no has abierto los ojos, echa un vistazo al siguiente código (2), no digas que no lo encontraste, tos, qué está pasando, sigo diciendo tonterías, prometo no decirlo. de nuevo.
{Código (1)
prueba dl, dl
jz +$08
añadir especialmente, -$10
llamar a @ClassCreate }
{///Código (2)
Procedimiento Tapplication.CreateForm(InstanceClass: TComponentClass; var Reference);
var
Instancia: TComponent;
comenzar
//////// Instancia := TComponent(InstanceClass.NewInstance);
TComponent(Referencia) := Instancia;
intentar
//////// Instancia.Create(Self);
excepto
TComponent(Referencia):= nil;
aumentar;
fin;
si (FMainForm = nil) y (La instancia es TForm) entonces
comenzar
TForm(Instancia).HandleNeeded;
FMainForm := TForm(Instancia);
fin;
fin;
}
En este caso, es decir, Delphi llama al código (1) cuando se llama por primera vez a la instancia de la clase creada. Entonces, si alguien necesita llamar al método Create, yo, no, es el compilador, solo. como este MOV dl, 0, de modo que la instrucción de salto de juicio 0 en el código (1) irá al lugar donde debería ir (¿Por qué estás diciendo tonterías otra vez? La última vez, lo prometo). De hecho, el método Crear aquí es solo un. método ordinario y , también debe notar que la primera llamada al método Create o al método NewInstance es la clase que envía este mensaje (tenga en cuenta que este mensaje no es Mensaje de Windows, este mensaje no es el otro mensaje, jaja, es una tontería de nuevo, realmente es la última vez, es verdad. Si no comprende el mensaje aquí, aprenda cuidadosamente los conocimientos de modelado y orientación a objetos) y llame. Más tarde, el método Create es un objeto establecido, Instance.Create(Self), piénselo, por supuesto, el valor del registro dl ha cambiado.
Bueno, no tengo mucho tiempo. Finalmente, me gustaría agregar eso con respecto a la bandera (método de traducción de Taiwán, creo que esta palabra es buena, te sugiero que la uses también para ahorrarme muchos problemas más adelante) y el. Instrucciones para el uso de este registro dl, debe decirse que no habrá ningún cambio. Si lo piensa detenidamente, Delphi no ha cambiado de 1 a 6. Por cierto, también demuestra que el diseñador HB de Delphi es un. personaje. Por supuesto, no puedo comparar. Jaja, aquí vamos de nuevo, está bien, dejaré de hablar. Ah, finalmente, déjame decirte que el método TObject.Create no es de ninguna manera un método vacío, recuerda y luego piensa en ello.
Bueno, otras cosas, ve a verlas en persona. En ese caso, ganarás mucho.
"¡Sal de aquí, quiero verlo y pensar en ello, y no quiero tus tonterías!" :)
adiós
Cuando el compilador asigna memoria para un objeto, el soporte que proporciona es insertar estas líneas de código ensamblador antes de llamar al constructor:
prueba dl, dl
jz +$08
añadir especialmente, -$10
llamar a @ClassCreate // Presta atención a esta línea de código
La última línea del código anterior llama a la función _ClassCreate en la línea 8949 del archivo system.pas (sujeto a Delphi 6). Esta función asigna específicamente la memoria adecuada para cada objeto. Una vez completada la asignación de memoria, se llama al constructor de la clase para inicializar los miembros de datos. Posteriormente, el compilador insertará las siguientes líneas de código ensamblador:
prueba dl, dl
jz +$0f
llamar a @AfterConstruction
pop dWord ptr fs:[$00000000]
añadir esp, $0c
El trabajo principal es llamar a AfterConstruction de cada instancia de objeto. Esta llamada no tiene ninguna utilidad en Delphi. Su existencia está reservada para C++Builder.
De manera similar, al destruir un objeto, primero se debe llamar al destructor de la clase para liberar los recursos solicitados por el objeto. Después de eso, el espacio de memoria ocupado por el objeto en sí se recicla. Este trabajo lo completa el compilador insertando el siguiente código ensamblador después de llamar al destructor:
llamar a @BeforeDestruction
prueba dl, dl
jle +$05
llamar a @ClassDestroy
El trabajo realizado por estos códigos corresponde a lo que se realiza al construir el objeto y asignar memoria, principalmente llamando a la función _ClassDestroy en la línea 8997 en system.pas.
constructor y destructor
Para definir un constructor, use la palabra clave Constructor. Por convención, el nombre del constructor es Crear (por supuesto, se pueden usar otros nombres, ¡pero de ninguna manera es un buen diseño!). como:
tipo
TMyFamily = class // La clase definida para tu familia
Privado
FMyFatherName: String // el nombre de tu padre
FMyMotherName : String // el nombre de tu madre
… // Otros miembros de tu familia
Público
Constructor Create(strFatherName, strMotherName: Cadena);
…… // Otros métodos
Fin;
Quizás se pregunte, si no proporciono un constructor para mi clase, ¿se pueden crear sus objetos? La respuesta es: sí. El motivo se ha mencionado antes: el compilador completa la asignación de la memoria ocupada por el objeto en sí. Y dado que en Object Pascal todas las clases (excepto la propia clase TObject) se derivan de la clase TObject, el compilador llamará al constructor TObject.Create(), pero esta función es una función vacía y no afectará a la clase TMyFamily. Cuando se inicializan los miembros de datos (FMyFatherName, FMyMotherName), se borrarán automáticamente y quedarán como cadenas vacías (es decir, ''), porque TObject.Create() no conoce a tu padre ni a tu madre en absoluto.
Al crear un objeto, se llama directamente al constructor, de la siguiente forma:
MyFamilyObject := TMyFamily.Create('Zhang', 'Li');
Utilice la palabra clave Destructor para definir un destructor. Por convención, el destructor se denomina Destroy. como:
tipo
TMiClase = clase
Público
Destructor Destruir(); anular;
Fin;
La razón por la que se agrega una declaración de anulación al final de la declaración del destructor es para garantizar que el objeto se pueda destruir correctamente en el caso de polimorfismo (el polimorfismo se discutirá en detalle en la Sección 2.4). Si no agrega la palabra clave override, el compilador dará una advertencia similar a "El método 'Destruir' oculta el método virtual del tipo base 'TObject'". La advertencia significa que el Destroy que definiste oculta el método virtual TObject.Destroy() de la clase base. En ese caso, el objeto no se puede destruir correctamente en situaciones polimórficas.
Nota: Los destructores deben declararse con una declaración de anulación.
Del mismo modo, si no hay recursos especiales que deban liberarse en su clase, no necesita definir un destructor. Sin embargo, al destruir un objeto, debes llamar al método Free() del objeto en lugar de llamar a Destroy() directamente.
MiFamilyObject.Free();
Esto se debe a que el método Free() determinará si el objeto en sí es nulo y, si no es nulo, se llamará a Destroy() del objeto para aumentar la seguridad. Ahora que existen formas más seguras de hacer esto, ciertamente no hay razón para no hacerlo.
Nota: Nunca llame a Destroy() directamente en un objeto, sino a Free().
De esto se puede concluir que en Object Pascal solo debe prestar atención a la asignación y liberación de los recursos solicitados por el objeto, ¡y no debe preocuparse por el espacio ocupado por el objeto en sí!