Skip to main content
gamedev.net
🔒 Locked

Accessing objects via array index vs. pointers

Started by IADaveMark 6 replies 250+ views
Original Post
IADaveMark
IADaveMark
Ok... I find myself in a major quandry. I began this project by setting up classes as follows:
      
cMyClass

cMyClassCollection
    cMyClass* MyClassCollection[100];

//*********


cMyOther

cMyOtherCollection
    cMyOther* MyOtherCollection[300];
    short ClassID; //an index in MyClassCollection


//*********


//etc... I have many of these class/collection pairs  

  
Notice that the objects are on the heap and I am creating an array of pointers to those objects. Now, for some of my collections... I created STL lists instead... for example:
        
typedef std::list<cMyObjects*> MY_LIST;

class cMyObjectsCollection
     MY_LIST MyList;
      
The result is similar in that I end up with a list of pointers to objects that are created on the heap. My problem with method one stems from the fact that a lot of times these classes need to grab information (either data or results of functions) from many other classes. What's worse, there are often times when I have to cascade through a number of classes to do this. For example, A is a B which is of type C. A now needs to get data from C via it's relationship with B. I realize that I can create a function in A which retrieves a function in B which retrieves a function in C... but my problem is as follows. If we are storing the relationships between A-B and B-C as index IDs for the BCollection and CCollection objects, we need to have a reference to those collections. If A needs to ask BCollection about a particular B, I need to have passed in a reference to BCollection. Subsequently, the call to B (from BCollection) will need to have a reference to CCollection so that B can get the data (eventually) from C. It would seem that the original call to A would have to have references to BCollection AND CCollection. When I shifted to using pointers instead, I didn't have to have A go through BCollection but rather called a function of B directly using mMyData = B->MyFunction(); B->MyFunction() could then call C directly by pointer using return C->CsFunction(); I thought my problem was solved. Of course, then I realized that I have no way of loading data from the file that says A is of this specific type of B. I had originally stored the index of BCollection that A was refering to... obviously I can't store the pointer the same way. I made a quick effort to change my data load function to ask BCollection to return the pointer to a B object when I gave it the index to the array. However, I had originally been calling the data load function of ACollection in its constructor and I ran into some issues so I quickly backed out my changes prior to rethinking the issue. That brings me to you guys... I have many objects here to deal with with some very complicated relationships between them. At times, they may need to access data/functions from many different other objects of other classes. I am loathe to have all my function calls passing around &references to very many different classes unless that is the best way to go. How is this sort of issue generally handled? Is it common to pass references to 4-6 different class objects around at all times? Is there any value to creating a master object to pass around where the various collection objects are members of it? Are pointers the way to go instead so I can just get directly to the specific object I want to store as member data? If so, what is a good technique for saving references such as that in data files other than how I mentioned (saving an index to an array of pointers and converting the index to the actual pointer as you load it)? Your help would be appreciated! Dave Mark - President and Lead Designer Intrinsic Algorithm - "Reducing the world to mathematical equations!" RIPPL Sports - NFL Statistical Analysis and Prediction System [edited by - InnocuousFox on January 24, 2003 5:50:21 PM] [edited by - InnocuousFox on January 24, 2003 5:51:13 PM]
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
IADaveMark
IADaveMark
What? Not even ONE suggestion before it fell off the front page? I figured surely someone would jump in on this! Anyone? Anyone?

Dave Mark - President and Lead Designer
Intrinsic Algorithm -
"Reducing the world to mathematical equations!"
RIPPL Sports - NFL Statistical Analysis and Prediction System
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
IADaveMark
IADaveMark
Again off the front page?! *gasp*

Dave Mark - President and Lead Designer
Intrinsic Algorithm -
"Reducing the world to mathematical equations!"
RIPPL Sports - NFL Statistical Analysis and Prediction System
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
IADaveMark
IADaveMark
quote:
Original post by InnocuousFox
How is this sort of issue generally handled?

Is it common to pass references to 4-6 different class objects around at all times?

Is there any value to creating a master object to pass around where the various collection objects are members of it?

Are pointers the way to go instead so I can just get directly to the specific object I want to store as member data?

If so, what is a good technique for saving references such as that in data files other than how I mentioned (saving an index to an array of pointers and converting the index to the actual pointer as you load it)?




Dave Mark - President and Lead Designer
Intrinsic Algorithm -
"Reducing the world to mathematical equations!"
RIPPL Sports - NFL Statistical Analysis and Prediction System
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
Qw3r7yU10p!
Qw3r7yU10p!
So, you''re not really asking about arrays and pointers but about how to handle all the interactions between your classes. Hmm, not surprised you got few takers with the title of the thread.

I''d recommend refactoring and the associated book to help get a feel for what-should-go-where.

There are lots of articles linked from the page. Explore.

For example if you have a class that all the functions take a certain object then there are two ideas:
1) the functions should really be on the class you keep passing instances of.
2) the class should contain the data and behaviour of the passed class.

There are often two opposite directions that you can change the design of your code and it really depends on the context and other inter-dependencies. There are no hard and fast rules but putting on the refactoring hat can help.
IADaveMark
IADaveMark
Let me give an example then. Here are some relationships:

A flight is assigned an aircraft.
An aircraft is of a certain config (seating, etc.)
An aircraft is of a certain type (which gives us size, body style)

To calculate the estimated passenger loading time for the flight, we need to know the number of seats (from "config") and the body style (e.g. narrow, wide, commuter from "type").

My classes are as follows.

Flight //has a pointer to aircraft
FlightCollection //std::list of flights

Aircraft //needs a config and a type - index or pointer?
AircraftCollection //std::list of aircraft

Config //also point to type - has functions for returning boarding times
ConfigCollection //either array or list?

Type
TypeCollection //either array or list?

Does that help?

Dave Mark - President and Lead Designer
Intrinsic Algorithm -
"Reducing the world to mathematical equations!"
Dave Mark - President and Lead Designer of Intrinsic Algorithm LLC
Professional consultant on game AI, mathematical modeling, simulation modeling
Co-founder and 10 year advisor of the GDC AI Summit<
Qw3r7yU10p!
Qw3r7yU10p!
Okay, there are a number of different ways to take this in (as I said)

The body style could just be an integer or an enumerated type but you can actually make it do more work than that. There are refactoring methods to change enumerations into useful and functioning classes.

The body style will determine how long it takes to get people on and off so it would be good to have the function which calculates on the bodystyle class. (this decision to put the function on this particular class also comes from there not being an 'aircraft capacity' class, which feasibly could take a body-style class and do the calculation. Ie move it the other way. I assume you don't have a 'capacity' class and just represent the number of passengers as an integer. So, pass the integer to the bodystyle class and get it to calculate the loading/unloading time. Remember, it could have gone the other way and in a slightly different situation it would have. Sometimes if you can't make up your mind, there is no obvious place that a function belongs, the pros and cons don't make much odds, then it probably doesn't matter. Just make a choice.

All the body styles would become subclasses of a base type. If they didn't hold any state information they could just be a static instance somewhere in your design which gets used as a member reference. If the style holds state info then they'll have to be individual instances.

As I say, read up on refactoring. It's a good book, worth the money in my opinion.

Hope all this helps. You may find my solution doesn't fit because of other considerations but hopefully it will have given you a way to think about it.

[edited by - petewood on January 26, 2003 11:05:03 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.