PDA

View Full Version : Another Pointer Question - TObjectList



Gadget
30-03-2005, 07:12 PM
Hi,

Sorry for asking what may sound like stupid questions, but I am yet again stuck with bl**dy pointers...

I have a TObjectList with a load of TCreatures in it.

I have a pointer type to a creature which works fine:-

type PCreature = ^TCreature;


I have a PCreature variable that I want to use to control my 'player' creature.

eg. Player: PCreature;

What I need to do is get the pointer to the actual TCreature in the List:-

Something like:-

Player := @lstCreatures.Items[iX];

But it says 'variable required'. What am I doing wrong here? Can I not get a pointer to it this way?

Thanks for your patience =D

M109uk
30-03-2005, 07:25 PM
Hi Gadget,

The problem is the following code:

Player := @lstCreatures.Items[iX];

Change it to:

Player^ := lstCreatures.Items[iX];


this should do the trick :D

Gadget
30-03-2005, 07:38 PM
Hi Gadget,

The problem is the following code:

Player := @lstCreatures.Items[iX];

Change it to:

Player^ := lstCreatures.Items[iX];


this should do the trick :D

Thanks, but I still have a problem =/

If I do what you suggested it says:- Incompatible types 'TCreature and TObject'

If I type cast it like this:-

Player^ := TCreature(lstCreatures.Items[iX]);

I get an access violation?

M109uk
30-03-2005, 07:43 PM
Ok, i guess that was expected lol
I mostly use TList and i use a function like:

function TMyList.GetItem(Index: Integer): TMyObject;
begin
Result := Nil;
If (Index < 0) Or (Index > Count-1) Then Exit;
Result := TMyObject(inherited Items[Index]);
end;


Try using:

Player := TCreature(lstCreatures.Items[iX]);

Gadget
30-03-2005, 07:47 PM
Ok, i guess that was expected lol
I mostly use TList and i use a function like:

function TMyList.GetItem(Index: Integer): TMyObject;
begin
Result := Nil;
If (Index < 0) Or (Index > Count-1) Then Exit;
Result := TMyObject(inherited Items[Index]);
end;


Try using:

Player := TCreature(lstCreatures.Items[iX]);


Now I get Incompatible types 'TCreature' and 'PCreature'

:?

M109uk
30-03-2005, 08:01 PM
hmm ok.. giv me a sec to get some code up..

Do you need to use:
Player: PCreature; ?
cant you use TCreature instead??

Not sure if it will work but i dont get any errors:

Player := Pointer(lstCreatures[i]);

Gadget
30-03-2005, 09:04 PM
hmm ok.. giv me a sec to get some code up..

Do you need to use:
Player: PCreature; ?
cant you use TCreature instead??

Not sure if it will work but i dont get any errors:

Player := Pointer(lstCreatures[i]);


If I use PCreature it means I don't have to type cast it. I don't know if that's the best way of doing it or not?

Alternatively I could type cast it when I need to use it:-

eg.

TCreature(Player).DoAction;

as opposed to

Player.DoAction;

I really need to get to grips completely with pointers and pointers to types :?

I have used pointers throughout the game so far with no problems, it's just this that's bugging me (litteraly)

Anonymous
30-03-2005, 10:31 PM
Hi, Player := @lstCreatures.Items[iX];

=D

lstCreatures.Items , must be type TCreature, if not, error will occur..

M109uk
31-03-2005, 01:41 AM
If I use PCreature it means I don't have to type cast it. I don't know if that's the best way of doing it or not?

Alternatively I could type cast it when I need to use it:-

eg.

TCreature(Player).DoAction;

as opposed to

Player.DoAction;

I really need to get to grips completely with pointers and pointers to types

I have used pointers throughout the game so far with no problems, it's just this that's bugging me (litteraly)


I see your point, is there a particular reason why you use TObjectList, you could always use TList which instead of resulting with TObject TList results the pointer and you can base your own class on this.. e.g.


type
TCreature = Class
// TCreature code
public
Name: String;
procedure DoAction;
end;

TCreatures = Class(TList)
private
function GetCreature(Index: Integer): TCreature;
public
function Add(Name: String): Integer;
property Items[Index: Integer]: TCreature read GetCreature; default;
end;

implementation

//----< TCreature >----//
procedure TCreature.DoAction;
begin
// Action
end;

//----< TCreatures >----//

function TCreatures.GetCreature(Index: Integer): TCreature;
begin
Result := Nil;
If (Index < 0) Or (Index > Count-1) Then Exit;
Result := TCreature(inherited Items[Index]);
end;

function TCreatures.Add(Name: String): Integer;
var
nCreature: TCreature;
begin
nCreature := TCreature.Create;
nCreature.Name := Name;
Result := inherited Add(nCreature);
end;


and with this you can do what you want: Players[i].DoAction;

I find using this is a lot easier to deal with :D

hope it helps..

cairnswm
31-03-2005, 04:44 AM
Var
P : PCreature;
T : TCreature;
begin
T := TCreature(MyList[0]);
P := @T;
Edit1.Text:= IntToStr(P^.ID);
End;

I must say that I think you've missed the point of classes. In Delphi any variable of a class type is already a pointer. There is no reason to have a PType as a pointer to the class as you are effectivly creating a pointer to a pointer to the class instance. This PType structure basically is legacy from Turbo Pascal and should not be used anymore.

Just change your Player to be of type TCreature and you will effectly have achieved everything you need to do.

The only time you need PTypes in delphi is if you are using records and want to put them into something like an object list.

savage
31-03-2005, 09:00 AM
cairnswm is right, classes are already pointers so there is no need to declare a Pointer type for them. So by declaring a pointer type, you are essentially creating a Pointer to a Pointer.

{MSX}
31-03-2005, 09:37 AM
I must say that I think you've missed the point of classes. In Delphi any variable of a class type is already a pointer. There is no reason to have a PType as a pointer to the class as you are effectivly creating a pointer to a pointer to the class instance. This PType structure basically is legacy from Turbo Pascal and should not be used anymore.


This is exacly why i always tell around not to use pointers :)

Gadget
31-03-2005, 06:12 PM
cairnswm is right, classes are already pointers so there is no need to declare a Pointer type for them. So by declaring a pointer type, you are essentially creating a Pointer to a Pointer.

OK, so if I want to have a variable called Player that is actually an entry in the TObjectList, how do I do that?

Thanks ;)

cairnswm
31-03-2005, 07:26 PM
(Not tested in Delphi)


Type
TItem = Class
<properties>
End;
var
Items : TList;

Procedure Create;
Var
I : TItem;
Begin
Items := TList.Create;
I := TItem.Create;
I.Init;
Items.Add(I);
End;

Function GetItem(Index : Integer) : TItem;
Begin
Result := TItem(Items[Index]);
End;

Player := GetItem(0);

Anonymous
31-03-2005, 09:51 PM
The only time you need PTypes in delphi is if you are using records and want to put them into something like an object list.

yeah, or linked lists, or if one want to access memory address directly, if I'm not wrong, the purpose of OOP is to relieve the programmer of using pointers; however; I see myself using them quite a lot..

Anonymous
31-03-2005, 09:52 PM
The only time you need PTypes in delphi is if you are using records and want to put them into something like an object list.

yeah, or linked lists, or if one want to access memory address directly, if I'm not wrong, the purpose of OOP is to relieve the programmer of using pointers; however; I see myself using them quite a lot..but in a strict sense they should be avoided.

Anonymous
31-03-2005, 09:52 PM
[quote="cairnswm"]
The only time you need PTypes in delphi is if you are using records and want to put them into something like an object list.

yeah, or ]

savage
31-03-2005, 10:28 PM
I tend to like things more strongly typed so I would use something like

interface

type
TCreature = class( TObject )
// General Creature features
end;

TSpecialistCreatureA = class( TObject )
// SpecialistCreatureA features
end;

TSpecialistCreatureB = class( TObject )
// SpecialistCreatureB features
end;

TPlayer = class(TCreature)
// Specialise my Creature so it behaves more like a Player
end;

TCreatureManager = class( TObjectList )
protected
function GetItem(Index: Integer): TCreature;
procedure SetItem(Index: Integer; AObject: TCreature);
public
function Extract(Item: TCreature): TCreature;
function First: TCreature;
function Last: TCreature;
property Items[Index: Integer]: TCreature read GetItem write SetItem; default;
end;

implementation

{ TCreatureManager }
function TCreatureManager.Extract(Item: TCreature): TCreature;
begin
result := TCreature(inherited Extract(Item));
end;

function TCreatureManager.Last: TCreature;
begin
result := TCreature(inherited Last);
end;

function TCreatureManager.GetItem(Index: Integer): TCreature;
begin
result := TCreature(inherited Items[Index]);
end;

function TCreatureManager.First: TCreature;
begin
result := TCreature(inherited First);
end;

procedure TCreatureManager.SetItem(Index: Integer; AObject: TCreature);
begin
inherited Items[Index] := AObject;
end;

end.


This does compile in Delphi.

If you really need to, you could also override the Add, Insert and other methods within the TObjectList decendant if you need to do some special things when adding etc. But as it is this code should handle managing a list of creatures and their decendents.

marmin
01-04-2005, 01:30 AM
That code looks solid.
OOP at it's best!

cairnswm
01-04-2005, 05:21 AM
I agree on the specialised objects.

For Run-A-War I think there are 17 different classes. Lots of classes only really helps if you use polymorphism properly.

Gadget
01-04-2005, 05:23 PM
Thanks! I will have another go later. I don't think the root of my problem is where I think it is...

I have used strongly typed stuff for the server, but for the client all 'Creatures' are essentially the same.