Archived

This topic is now archived and is closed to further replies.

constructor problems

This topic is 5384 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I always hear about how initilization should be done in the constructor and only the constructor. I have a class ParticleSystem that has a lot of attributes, such as position, emissionRate, particle size, speed, etc etc. So I made a special class just to hold these attributes that looks like this:
class ParticleSystemDescriptor {
public:
	int numParticles;
	Point position;
	Vector forces;
	Vector direction;
	int emissionRate;
	float particleSize;
	float particleLifeTime;
	float emissionSpeed;

};
 
Consequently, my constructor for the Particle System takes one reference argument like this: ParticleSystem(ParticleSystemDescriptor& psd); Since I need to refer to my particle system in both the update() and draw() functions, I decided it was best to make the Particle system global. But when I try to do this:
ParticleSystemDescriptor psd;
psd.direction.set(1, 1, 1);
psd.emissionRate = 10;
psd.emissionSpeed = 10;
psd.forces.set(0, -1, 0);
psd.numParticles = 100;
psd.particleLifeTime = 1000;
psd.particleSize = 1;
psd.position.set(0,0,0);
	
ParticleSystem ps(psd);
 
outside of any functions at the top of my main.cpp, the compiler complains. I guess its because you cant have ''real'' code outside of functions, such as all my calls to psd.whatever. I hope everyone understands what I am trying to do and that you are not getting confused instead. I would like suggestions on how to make this work, or perhaps a better design to avoid this problem altogether. Thanks in advance.

Share this post


Link to post
Share on other sites
I don't see the benefit here of having all your attributes in a seperate wrapper class. It seems like just an extra step to work with your particle system's data. These attributes are specific to the particle system, so they should preside in the class directly. There might be some cases where you want a wrapper class, but this doesn't look like one of them.

While it's true that your constructor should do initialization, that doesn't have to be the only place where initialization of member data can occur. For example, you can have a seperate Init() or Reset() function that does just that, reset or initialize your data, depending on what other types of functions your particle system class will have.

That being said, the constructor should be able to set default values for your member variables (either directly or indirectly) itself, and not have to rely on code outside setting these values. It should have some idea on how to set itself up.

[edited by - Zipster on March 23, 2003 8:56:05 PM]

Share this post


Link to post
Share on other sites
Zipster, thank you for you reply.

I read somewhere that when you have to pass tons and tons of arguments to a function (or constructor), that it is a good idea to stick them all in a structure (or class) first, and then just pass that structure in. That way, everything looks a lot cleaner. Otherwise, my code would have looked like this:


ParticleSystem ps(Vector(1, 1, 1), 10, 10, Vector(0, -1, 0), 100, 1000, 1, Point(0,0,0));


My wrapper dealie wasnt really an ''extra step'', because inside my constructor, the first thing i did was extract everything from the structure that was passed in and store them in regular member variables. Maybe this wasnt a good idea ?

So barring the wrapper thing, you think my overall structure is ok? Like, its ok to make my particle system global? And I was right about why the compiler halted-- that you cant set the values of ParticleSystemDescriptor when your not inside the body of a function?

Thanks again for your help.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Don''t believe all you read.

An object should initialize itself to some point where it is in "legal" state, in the constructor. This may be as easy as just zeroing out any member pointers, or relying on containers to create themselves empty.

Then there''s a configuration step in the object lifetime, which is very important. Here''s where the object actually acquires pointers to helpers/managers/doodads, parses configuration files, and all that good stuff.

Once the object is fully configured, you can tell it to start operating, at which point it''ll assert if it''s not consistently configured. After it''s started correctly, you can let the object do what it''s supposed to do (such as "update state" and "render".

At the end, there''s deleting the object. You may want to split that off into stopping, clearing configuration, and actual deletion, if you want to be able to take objects in and out of active sets and whatnot, and/or re-use objects (which may make sense if the object is some scarse resource you don''t want to fragment).


Note that this is a rather higher-level, interface-level view to object-as-subsystem. For objects which are simple value classes or containers, having the constructor be initialization of everything, and having the object be operating after constructor, is a good idea. Use the right tool for the right design challenge.

Share this post


Link to post
Share on other sites