2010-09-29 16 views
5

Ho bisogno di ottenere puntatore alla mia istanza di classe all'interno di questa istanza. Non posso usare direttamente "Self", ho bisogno di un puntatore del negozio per un utilizzo futuro. Ho provato codice successivo:Uso Delphi Self-Pointer

type 
    TTest = class(TObject) 
    public 
     class function getClassPointer: Pointer; 
     function getSelfPointer: Pointer; 
    end; 

class function TTest.getClassPointer: Pointer; 
begin 
    Result := Pointer(Self); 
end; 

function TTest.getSelfPointer: Pointer; 
begin 
    Result := Pointer(Self); 
end; 

Ed entrambi risultato sono sbagliato - questo codice:

test := TTest.Create; 
Writeln('Actual object address: ', IntToHex(Integer(@test), 8)); 
Writeln('Class "Self" value: ', IntToHex(Integer(test.getClassPointer()), 8)); 
Writeln('Object "Self" value: ', IntToHex(Integer(test.getSelfPointer()), 8)); 

rendimenti:

Actual object address: 00416E6C 
Class "Self" value:  0040E55C 
Object "Self" value:  01EE0D10 

Ti prego, aiutami a capire, che cosa è questo valore "Sé" ? "Sé" è un puntatore a questa istanza di classe? Come utilizzare questo puntatore per un utilizzo futuro al di fuori di questo oggetto? Come ottenere il puntatore corretto da questo valore?

risposta

12

Stai cercando di confrontare tre entità completamente diverse.

@test restituisce l'indirizzo del test della variabile, non l'istanza dell'oggetto a cui punta.

test.getClassPointer() restituisce l'indirizzo dei metadati della classe, una struttura di dati costante generata dal compilatore in cui il runtime può trovare la tabella del metodo virtuale, le tabelle di informazioni sul tipo di runtime e altro. Tutte le istanze di una classe condividono la stessa struttura di metadati di classe. Il puntatore ai metadati della classe è l'identità del tipo dell'istanza dell'oggetto - è come l'oggetto sa di che tipo è in fase di runtime.

test.getSelfPointer() fornisce l'indirizzo effettivo dell'istanza dell'oggetto nella memoria. Due istanze di oggetto (create separatamente) avranno indirizzi di istanze differenti. test.getSelfPointer() sarà uguale al contenuto della variabile istanza test: Pointer (test)

Ad esempio (pseudocodice, non testato):

type TTest = class 
    end; 

var test1: TTest; 
    test2: TTest; 

begin 
    test1 = TTest.Create; // allocates memory from the global heap, stores pointer 
    test2 = test1;   // copies the pointer to the object into test2 variable 
    writeln("Test1 variable points to: ", IntToHex(Integer(Pointer(test1)))); 
    writeln("Test2 variable points to: ", IntToHex(Integer(Pointer(test1)))); 
end. 
+1

Grazie! Ora capisco come usare questo! TTest (Puntatore (test)) o TTest (test.getSelfPointer()) - è ciò di cui ho bisogno =) – soar

+4

Questi sono costrutti molto strani per Delphi.Sei sicuro di non rendere le cose troppo complicate per te stesso? il tuo foo = TTest (Pointer (test)) equivale a dire foo = test. Ogni variabile di istanza dell'oggetto in Delphi è in realtà un puntatore. Il pointerness è appena sotto la superficie. – dthorpe

+1

Inoltre, 'getClassPointer' è lo stesso del metodo' ClassType' incorporato. –

0

Nel frammento di codice test è già un riferimento al reale esempio, così si dovrebbe provare

Writeln('Actual object address: ', IntToHex(Integer(Pointer(test)), 8)); 

E probabilmente non è necessario alcun metodo getSelfPointer. Se si desidera un secondo riferimento all'istanza dell'oggetto che già test riferimenti, scrivono:

var 
    SecondReferenceToTest: TTest; 
SecondReferenceToTest := test; 

di vedere questo, provare qualcosa di simile:

type 
    TTest = class(TObject) 
    public 
    Name: string; 
    end; 

procedure TestProc; 
var 
    test, SecondReferenceToTest: TTest; 
begin 
    test := TTest.Create; 
    try 
    test.Name := 'Named via "test" reference'; 
    SecondReferenceToTest := test; 
    ShowMessage(SecondReferenceToTest.Name); 
    finally 
    test.Free; 
    end; 
end; 
+0

questo modo - ottenere riferimento al di fuori dell 'oggetto, ma cosa devo fare per restituire un puntatore valido all'interno del metodo di questo oggetto? Come nel mio esempio. – soar

+0

@Soara, se hai intenzione di chiamare un metodo sull'oggetto, allora * hai * un riferimento all'oggetto. L'oggetto stesso non ha accesso "speciale" ad esso. All'interno di un metodo di istanza 'Self' è un riferimento all'oggetto, lo stesso riferimento che i chiamanti devono avere già se chiamano metodi sull'oggetto. All'interno di un metodo di classe, 'Self' è un riferimento alla classe, non ad alcuna istanza della classe. –

+0

La mia domanda - è solo un campione, in realtà uso la struttura, dove l'oggetto è collocato in un altro oggetto come campo e non c'è "test" al suo interno. Ora posso passare ad esso puntatore corretto. Grazie a tutti ! – soar