class object
{
public:
int x,y;
};
class bullet : public object
{
int damage;
int speed;
};
class level_data
{
public:
object *bullet_list;
};
[/source]
This all seems to work fine. Bullet list is going to be an array of bullet objects. But look at this
[source]
level_data level;
level.bullet_list = new bullet[50];
Now I would think that this would work, but unfortunately I have no such luck. You can access them as if they were class bullet''s but the problem is that they do not get allocated enough memory so if you write to a variable in the first element of the array you overwrite data in the second, and so on.
Does anyone know why this happens? I am using MSVC if it makes a difference...
wise_guy
new not working?
Hi all!
okay, let''s say I have classes like this
bullet_list is of type object , but you're treating it as if it's of class bullet . A pointer to object has to point to memory thats of type object , not bullet .
If you didn't understand what i just said (im sure you would of), just change this:
to
Edited by - Zipster on September 9, 2000 12:20:00 AM
If you didn't understand what i just said (im sure you would of), just change this:
level.bullet_list = new bullet[50];
to
level.bullet_list = new object[50];
Edited by - Zipster on September 9, 2000 12:20:00 AM
Wait. The way you''re doing it seems right now that i think of it. I guess you can try my way. AHH, now i see it:
change:
to:
Someone else can verify that the syntax on the second line is correct.
=======================================
A man with no head is still a man.
A head with no man is plain freaky.
change:
level.bullet_list = new bullet[50];
to:
level.bullet_list = (object)new bullet[50];
Someone else can verify that the syntax on the second line is correct.
=======================================
A man with no head is still a man.
A head with no man is plain freaky.
Ok, here''s the deal. you can use a Bullet object in a place expecting an Object, and you can allocate them as you just have, etc. BUT you are dealing with ARRAYS ... which is NOT the same thing as POINTERS TO OBJECTS ... you do NOT have an array of pointers ... which could be polymorphic... you have an array of OBJECTS .. which CANNOT be polymorphic. You are confusing the fact that an ARRAY in C/C++ is a pointer, which points to the first item, with the fact that polymorphism uses pointers.
The best way to see this is to think it through like the computer. You must look at it from the point of view of the level data class. In any code in the level data class, the compiler thinks it has a pointer to an object ... and if you do pointer arithmatic on that pointer ... like bullet_list+i, bullet_list++, or bullet_list[1], the computations are all going to be computed using the equivilent of "sizeof(object)" so if you store something in bullet_list[5] ... that is the same as storing it at the address bullet_list + (5 * sizeof(object)) which is obviosly not the intended bullet_list + (5 * sizeof(object)).
So you see the problem. There are many ways to do what you MIGHT want to do ... depending on what that is . But the most general purpose answer to your problem is that you need and array of object POINTERS. like this.
class level_data
{
public:
object **bullet_list;
OR (this ones worst)
object *bullet_list[50]
OR (this one''s best IF size is static, typdefing object_ptr is still best)
typedef object* object_ptr;
object_ptr bullet_list[50];
};
level_data level;
level.bullet_list = new object_ptr[50]
for(int i=0;i<50;i++)
level.bullet_list = new bullet;
Hope that helps ... ask if you have more questions.
The best way to see this is to think it through like the computer. You must look at it from the point of view of the level data class. In any code in the level data class, the compiler thinks it has a pointer to an object ... and if you do pointer arithmatic on that pointer ... like bullet_list+i, bullet_list++, or bullet_list[1], the computations are all going to be computed using the equivilent of "sizeof(object)" so if you store something in bullet_list[5] ... that is the same as storing it at the address bullet_list + (5 * sizeof(object)) which is obviosly not the intended bullet_list + (5 * sizeof(object)).
So you see the problem. There are many ways to do what you MIGHT want to do ... depending on what that is . But the most general purpose answer to your problem is that you need and array of object POINTERS. like this.
class level_data
{
public:
object **bullet_list;
OR (this ones worst)
object *bullet_list[50]
OR (this one''s best IF size is static, typdefing object_ptr is still best)
typedef object* object_ptr;
object_ptr bullet_list[50];
};
level_data level;
level.bullet_list = new object_ptr[50]
for(int i=0;i<50;i++)
level.bullet_list = new bullet;
Hope that helps ... ask if you have more questions.
September 10, 2000 01:02 AM
Wouldn''t it be more simple to change this:
class level_data
{
public:
object *bullet_list;
};
to this
class level_data
{
public:
bullet *bullet_list;
};
?????
instead of getting all funky
class level_data
{
public:
object *bullet_list;
};
to this
class level_data
{
public:
bullet *bullet_list;
};
?????
instead of getting all funky
Ahhhhhh..... thanks a heap! Yes Xai, I was getting polymorphism pointing and array pointing confused! But it''s that kind of perculiarity that isn''t explained in (beginner) textbooks. You actually have to try it out yourself and realise it doesn''t work and get the assistance of someone who knows their stuff...
Okay, seeing as the solution requires arrays of pointers to object (which polymorph into bullets), how can I tell an external class or function that I am dealing with bullets, and not normal objects, so as to do the data indexing correctly?
wise_guy
p.s. anonymous - the *idea* is that i can have a list of objects which I need to update (ie. that are on the screen), which could all be different, but can all be indexed by an object pointer:
object *onscreen_entities[NUM_ENTITIES];
onscreen_entities[current] = bullet[3];
onscreen_entities[current+1] = enemy[5];
onscreen_entities[current+2] = explosion[3];
all of which derive from object
Okay, seeing as the solution requires arrays of pointers to object (which polymorph into bullets), how can I tell an external class or function that I am dealing with bullets, and not normal objects, so as to do the data indexing correctly?
wise_guy
p.s. anonymous - the *idea* is that i can have a list of objects which I need to update (ie. that are on the screen), which could all be different, but can all be indexed by an object pointer:
object *onscreen_entities[NUM_ENTITIES];
onscreen_entities[current] = bullet[3];
onscreen_entities[current+1] = enemy[5];
onscreen_entities[current+2] = explosion[3];
all of which derive from object
The solution is as posted .. which I''ll admit was a little hard to digest in one read ... so here go''s:
To be able to deal with an array of polymorphic objects, it must be an array of pointers - or technically it could be references .. but that would be VERY unusual and confusing at first.
so lets assume you have this typedef:
typedef object* object_ptr;
then you would simply change this line:
object *bullet_list;
to this:
object_ptr *bullet_list;
and then create them the way I posted - which I''ll repeat:
level_data level;
level.bullet_list = new object_ptr[50]
for(int i=0;i<50;i++)
level.bullet_list = new bullet;
and then your question about the indexing .. is automatically fixed, because it is an array of POINTERS ... all of which are the same size, no matter what they point to (which is really the whole trick behind getting polymorphism to work). NOTE: this is also the same trick that alows a compiler to put a pointer to an object, inside that object, before definition is complete .. because the compiler already knows the size of the pointer.
To emphasis the details - here''s a little example.
// this example is given assuming a 32 bit x86 processor
double numbers[5]; // takes 40 bytes (5*sizeof(double))
char letters[40]; // takes 40 bytes (40*sizeof(char))
double *numPtrs[10]; // takes 40 bytes (10*sizeof(double*))
char *letterPtrs[10]; // takes 40 bytes (10*sieof(char*))
assumming that each of the above arrays was located at address 100 (to make comparison easier), then the following would be true:
&(numbers[2]) == 116
numbers+2 == 116
&(letters[2]) == 102
letters+2 == 102
&(numPtrs[2]) == 108
numPtrs+2 == 108
&(letterPtrs[2]) == 108
letterPtrs+2 == 108
understand? objects of different types vary in size, pointers do not. on 32 bit nmachines, pointers are 32 bits (on 64 bit machines, 64 bit pointers - but you don''t care as long as you always treat pointers as pointers).
NOW ... as a final note ... I want to say that the Anonymous poster wasn''t being silly or flipant. you had a list as follows:
object *bullet_list;
and he was sugesting that perhaps you really want this:
bullet *bullet_list;
which IS probably what you DO want, unless your list is named wrong. The only reason I did not answer you that way, is that I assume you need the general solution to your problem in case you did NOT want the subclass type. But let me explain why he (and I) think you either have a mis-named variable, or a mis-typed one. I understand that object is your polymorphic base type. But don''t think of your class heirarchy as having ONE base ... every class that has derivatives is also a base. So ... IF every single object in the bullet_list must be a bullet or a bullet derivative .. then it should be an array of bullet pointers ... understand ... they would STILL be objects, and they could still be based to other functions and used as general objects, but the level_data class would use them as bullets without any casting required. NOW .. if they are NOT all going to be bullets ... like in the onscreen_entities variable ... then they will be a more general class ... such as object* ... but you see .. you make each polymorphic pointer as narrow as possible ... the same object gets assigned to both lists .. .but it''s access is controled by what each pointer knows about it.
I''ll go into more detail on this if you ask for it.
Once again, good luck.
To be able to deal with an array of polymorphic objects, it must be an array of pointers - or technically it could be references .. but that would be VERY unusual and confusing at first.
so lets assume you have this typedef:
typedef object* object_ptr;
then you would simply change this line:
object *bullet_list;
to this:
object_ptr *bullet_list;
and then create them the way I posted - which I''ll repeat:
level_data level;
level.bullet_list = new object_ptr[50]
for(int i=0;i<50;i++)
level.bullet_list = new bullet;
and then your question about the indexing .. is automatically fixed, because it is an array of POINTERS ... all of which are the same size, no matter what they point to (which is really the whole trick behind getting polymorphism to work). NOTE: this is also the same trick that alows a compiler to put a pointer to an object, inside that object, before definition is complete .. because the compiler already knows the size of the pointer.
To emphasis the details - here''s a little example.
// this example is given assuming a 32 bit x86 processor
double numbers[5]; // takes 40 bytes (5*sizeof(double))
char letters[40]; // takes 40 bytes (40*sizeof(char))
double *numPtrs[10]; // takes 40 bytes (10*sizeof(double*))
char *letterPtrs[10]; // takes 40 bytes (10*sieof(char*))
assumming that each of the above arrays was located at address 100 (to make comparison easier), then the following would be true:
&(numbers[2]) == 116
numbers+2 == 116
&(letters[2]) == 102
letters+2 == 102
&(numPtrs[2]) == 108
numPtrs+2 == 108
&(letterPtrs[2]) == 108
letterPtrs+2 == 108
understand? objects of different types vary in size, pointers do not. on 32 bit nmachines, pointers are 32 bits (on 64 bit machines, 64 bit pointers - but you don''t care as long as you always treat pointers as pointers).
NOW ... as a final note ... I want to say that the Anonymous poster wasn''t being silly or flipant. you had a list as follows:
object *bullet_list;
and he was sugesting that perhaps you really want this:
bullet *bullet_list;
which IS probably what you DO want, unless your list is named wrong. The only reason I did not answer you that way, is that I assume you need the general solution to your problem in case you did NOT want the subclass type. But let me explain why he (and I) think you either have a mis-named variable, or a mis-typed one. I understand that object is your polymorphic base type. But don''t think of your class heirarchy as having ONE base ... every class that has derivatives is also a base. So ... IF every single object in the bullet_list must be a bullet or a bullet derivative .. then it should be an array of bullet pointers ... understand ... they would STILL be objects, and they could still be based to other functions and used as general objects, but the level_data class would use them as bullets without any casting required. NOW .. if they are NOT all going to be bullets ... like in the onscreen_entities variable ... then they will be a more general class ... such as object* ... but you see .. you make each polymorphic pointer as narrow as possible ... the same object gets assigned to both lists .. .but it''s access is controled by what each pointer knows about it.
I''ll go into more detail on this if you ask for it.
Once again, good luck.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement