Sobre alocação e reciclagem de memória de objeto
Não sei se alguém tem alguma ideia sobre como colocar o registro dl aqui. Se não, pense bem. Na verdade, antes do código a seguir (1), existe uma linha de código MOV dl, 1, então por que é assim? O motivo não é muito simples, a reutilização de código. Quanto ao uso do registro dl aqui, há uma introdução na ajuda do Delphi. Seja paciente e procure você mesmo. Se você encontrar, você será um mestre. Isso é aprender, não, aprender a pescar, não pedir peixe. Borland disse o seguinte: "Eu uso o registro dl para armazenar um sinalizador. Se o valor for 1, criarei o objeto. Caso contrário, não criarei o objeto. Se você estiver um pouco confuso, pense nisso novamente e." de novo. Se você ainda não abriu os olhos, então dê uma olhada no código a seguir (2), não diga que não encontrou, tosse, o que está acontecendo, continuo falando bobagem, prometo não falar de novo.
{Código (1)
teste dl, dl
jz +$08
adicione esp, -$10
ligue para @ClassCreate}
{///Código (2)
PRocedure Tapplication.CreateForm(InstanceClass: TComponentClass; var Referência);
var
Instância: TComponent;
começar
//////// Instância := TComponent(InstanceClass.NewInstance);
TComponent(Referência) := Instância;
tentar
//////// Instance.Create(Self);
exceto
TComponent(Referência) := nil;
elevação;
fim;
se (FMainForm = nil) e (Instância é TForm) então
começar
TForm(Instância).HandleNeeded;
FMainForm := TForm(Instância);
fim;
fim;
}
Nesse caso, ou seja, o Delphi chama o código (1) quando a instância da classe criada é chamada pela primeira vez. Então, se alguém precisar chamar o método Create, eu, não, é o compilador, só. como este MOV dl, 0, para que a instrução de salto de julgamento 0 no código (1) vá para o lugar onde deveria ir (Por que você está falando bobagem de novo? Da última vez, eu prometo.) Na verdade, o método Create aqui é apenas um. método comum, e você também deve notar que a primeira chamada para o método Create ou método NewInstance é a classe que envia esta mensagem (observe que esta mensagem não é Mensagem do Windows, esta mensagem não é a outra mensagem, haha, é um absurdo de novo, é realmente a última vez, é verdade. Se você não entendeu a mensagem aqui, por favor, aprenda o conhecimento de orientação a objetos e modelagem com cuidado) e ligue. mais tarde. O método Create é um objeto estabelecido, Instance.Create(Self); é claro que o valor do registro dl mudou.
Ok, não tenho muito tempo. Por fim, gostaria de acrescentar isso em relação à bandeira (método de tradução de Taiwan, acho que essa palavra é boa, sugiro que você também a use para me poupar muitos problemas mais tarde) e o instruções para o uso deste registro dl, deve-se dizer Não haverá nenhuma mudança Se você pensar bem, o Delphi não mudou de 1 para 6. A propósito, isso também prova que o designer HB do Delphi é um. personagem. Claro, não posso comparar. Haha, lá vamos nós de novo, ok, vou parar de falar. Ah, finalmente, deixe-me dizer que o método TObject.Create não é de forma alguma um método vazio, lembre-se, e então pense sobre isso.
Ok, outras coisas, por favor, vá vê-las pessoalmente. Nesse caso, você ganhará muito.
“Saia daqui, quero ver e pensar nisso, e não quero suas bobagens!” :)
tchau
Quando o compilador aloca memória para um objeto, o suporte que ele fornece é inserir estas linhas de código assembly antes de chamar o construtor:
teste dl, dl
jz +$08
adicione esp, -$10
chame @ClassCreate // Preste atenção nesta linha de código
A última linha do código acima chama a função _ClassCreate na linha 8949 do arquivo system.pas (sujeito ao Delphi 6). Esta função aloca especificamente memória apropriada para cada objeto. Após a conclusão da alocação de memória, o construtor da classe é chamado para inicializar os membros de dados. Posteriormente, o compilador irá inserir as seguintes linhas de código assembly:
teste dl, dl
jz +$0f
ligue para @AfterConstruction
pop dWord ptr fs:[$00000000]
adicione esp, $ 0c
A tarefa principal é chamar AfterConstruction de cada instância do objeto. Esta chamada não tem utilidade no Delphi. Sua existência é reservada para C++Builder.
Da mesma forma, ao destruir um objeto, o destruidor da classe deve primeiro ser chamado para liberar os recursos solicitados pelo objeto. Depois disso, o espaço de memória ocupado pelo próprio objeto é reciclado. Este trabalho é concluído pelo compilador inserindo o seguinte código assembly após chamar o destruidor:
ligue para @BeforeDestruction
teste dl, dl
jle +$05
ligue para @ClassDestroy
O trabalho realizado por esses códigos corresponde ao que é feito na construção do objeto e na alocação de memória, principalmente chamando a função _ClassDestroy na linha 8997 em system.pas.
Construtor e destruidor
Para definir um construtor, use a palavra-chave Constructor. Por convenção, o nome do construtor é Create (é claro que outros nomes podem ser usados, mas isso não é de forma alguma um bom design!). como:
tipo
TMyFamily = class // A classe definida para sua família
Privado
FMyFatherName : String; // nome do seu pai
FMyMotherName : String; // nome da sua mãe
… // Outros membros da sua família
Público
Construtor Create(strFatherName, strMotherName: String);
…… // Outros métodos
Fim;
Você pode perguntar: se eu não fornecer um construtor para minha classe, seus objetos poderão ser criados? A resposta é: sim. O motivo já foi mencionado anteriormente, a alocação da memória ocupada pelo próprio objeto é finalizada pelo compilador. E como no Object Pascal todas as classes (exceto a própria classe TObject) são derivadas da classe TObject, o compilador chamará o construtor TObject.Create(), mas esta função é uma função vazia e não afetará a classe TMyFamily . Quando os membros de dados (FMyFatherName, FMyMotherName) são inicializados, eles serão automaticamente limpos para strings vazias (ou seja, ''), porque TObject.Create() não conhece seu pai ou sua mãe!
Ao criar um objeto, o construtor é chamado diretamente, da seguinte forma:
MyFamilyObject := TMyFamily.Create('Zhang', 'Li');
Use a palavra-chave Destructor para definir um destruidor. Por convenção, o destruidor é denominado Destroy. como:
tipo
TMyClass = turma
Público
Substituição do destruidor();
Fim;
A razão pela qual a instrução override é adicionada no final da declaração do destruidor é para garantir que o objeto possa ser destruído corretamente no caso de polimorfismo (o polimorfismo será discutido em detalhes na Seção 2.4). Se você não adicionar a palavra-chave override, o compilador emitirá um aviso semelhante a "O método 'Destroy' oculta o método virtual do tipo base 'TObject'". O aviso significa que o Destroy que você definiu esconde o método virtual TObject.Destroy() da classe base. Nesse caso, o objeto não pode ser destruído corretamente em situações polimórficas.
Nota: Os destruidores precisam ser declarados com uma instrução override.
Da mesma forma, se não houver recursos especiais que precisem ser liberados em sua classe, não será necessário definir um destruidor. Entretanto, ao destruir um objeto, você deve chamar o método Free() do objeto em vez de chamar Destroy() diretamente.
MyFamilyObject.Free();
Isso ocorre porque o método Free() determinará se o objeto em si é nulo e, se não for nulo, o Destroy() do objeto será chamado para aumentar a segurança. Agora que existem maneiras mais seguras de fazer isso, certamente não há razão para não fazê-lo.
Nota: Nunca chame Destroy() diretamente em um objeto, mas sim Free().
Pode-se concluir que no Object Pascal você só precisa estar atento à alocação e liberação dos recursos solicitados pelo objeto, e não precisa se preocupar com o espaço ocupado pelo próprio objeto!