Reputation: 799
I am using Delphi XE3. And after studying the post Delphi - Maintaining Self References to an Object , I understand that a variable of a class type is actually a pointer that references an object.
Therefore, I write the following code to test that, as follows:
TMyClass = class
public
constructor Create(Name: string);
destructor Destroy;
function GetName: string;
private
FName: string;
end;
PMyClass = ^TMyClass;
constructor TMyClass.Create(Name: string);
begin
FName := Name;
end;
destructor TMyClass.Destroy;
begin
end;
function TMyClass.GetName: string;
begin
Result := FName;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
Item: TMyClass;
P: PMyClass;
begin
Item := TMyClass.Create('Jim');
P := PMyClass(Item);
OutputDebugString(PWideChar(Format('Address of object: %x; Address of variable Item: %x; Value of P: %x;',
[Integer(Item), Integer(@Item), Integer(P)])));
OutputDebugString(PWideChar(Format('Name is %s', [Item.GetName()])));
OutputDebugString(PWideChar(Format('Name is %s', [P.GetName()])));
end;
In my code, using PMyClass(Item) seems also get the object address, since Integer(PMyClass(Item)) is same as Integer(Item). However, it seems that with the pointer to the object, I cannot invoke any method, both P.GetName() and P^.GetName() will cause access violation. Why?
And my question is, whether I can use pointer to class in programming. Also whether it is necessary to use pointer to class since a variable of a class type has already held the object address.
Upvotes: 3
Views: 444
Reputation: 80107
Item
already is pointer to the instance of TMyClass
and you don't need to introduce excessive level of adressing.
NativeInt(Item)
gives you the number representation of the address. To get the same representation from P
, with proper type casting, you need to use P = @Item
and NativeInt(P^)
I don't see how pointers might be useful for your task.... BTW, what is your real problem?
Upvotes: 0
Reputation: 612794
PMyClass(Item)
This cast is wrong. Because Item
is TMyClass
but PMyClass
is ^TMyClass
. Item cannot be both TMyClass
and ^TMyClass
.
The invalid cast is why you encounter the access violation.
If you really did want to obtain a value that was ^TMyClass
then you would need to take the address of a TMyClass
value. An example from your code would be @Item
. So, Item
is TMyClass
, hence @Item
is ^TMyClass
.
There are situations where ^TMyClass
might be useful, but they are not apparent in any of the code you present. For instance, you might use a variable of type ^TMyClass
to hold a reference to a variable of type TMyClass
. In other words, the standard scenario where pointers are useful.
Upvotes: 5