Archived

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

easy question about constructors......

This topic is 5045 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

high, i understand that the purpose of a contructor is to initialize values of an object when you declare it. for example

health = 20;
mana = 30;
stamina = 100;

entity player(health,mana,stamina);

will send the 3 values to my contructor and in my contructor i would have to put

this->health = health;

this->mana = mana;

this->stamina = stamina   (note i know you dont HAVE to put this-> it just clears things up for me)

BUT, do i HAVE to initialize everything through parameters??? for example, could i have just done :

entity player(); //no () needed here???


then inside of the contructor

this->health = 20;
this->stamina = 30;
this->mana = 100;

i realize it would be a bit more hard-coded, but for my purposes it doesnt matter. in fact in the first example i should have just sent it the values (20,30,100) instead of declaring variables and sending them. but anyway, could i do this instead of using parameters??? or do i HAVE to use parameters?? thanks for any help you can give me!!! [edited by - graveyard filla on February 20, 2004 12:58:51 PM] [edited by - graveyard filla on February 20, 2004 12:59:29 PM]

Share this post


Link to post
Share on other sites
No, you don''t have to pass parameters. You should be sure to initialize every data member in your constructor. Otherwise, you could spend hours tracking down a strange bug caused by garbage in an uninitialized data member.

Share this post


Link to post
Share on other sites
if i'm not mistaken (Fruny since you showed me this ...feel free to correct):

class Example {
public:
Example ( );

private:
int data;
string name;
float height;
int health;
}

Example::Example ( )
// this is where you initialize your private members!
: data (25), name ("Alcor"), height (6.25), health (100)
{
// blah blah blah
}


[edited by - Alpha_ProgDes on February 20, 2004 1:08:46 PM]

Share this post


Link to post
Share on other sites
hey,

point of clarification. you said, "(note i know you dont HAVE to put this-> it just clears things up for me)". but in the case that the class''s member variable are exactly the same name as the parameters you most certainly DO have to use this->. otherwise you will be setting the parameter = parameter rather than member var = parameter. Function parameter names, if the same as member variable names will take precidence when the compiler tries to resolve which one you mean. so always use this if you have a parameter or local variable of the same name as a member variable name.

you could always have your constructor set up like:


Player()
{
health = DEFAULT_HEALTH;
mana = DEFAULT_MANA;
stamina = DEFAULT_STAMINA;
}

//or


Player( health = DEFAULT_HEALTH, mana = DEFAULT_MANA, stamina = DEFAULT_STAMINA )
{
this->health = health;
this->mana = mana;
this->stamina = stamina;

}


in the latter case the passing of parameters is essentially optional. if you don''t pass parameters they will be set to the DEFAULT_ series of values. that way you only need to pass them for special case things.

you could also set it up so that character stats are read in from a text file that you can more easily change. so the Player constructor would look something like:


Player( char * fileName )
{
loadStatsFromFile( fileName );
}


this last example is a great way to go (data driven design) because it means that you don''t need to recompile your code to set the various values for you in game objects.

-me

Share this post


Link to post
Share on other sites
1) You can do this, but that means you have to make your data members public, which defeats the purpose of encapsulation (if it''s a class) and you have to ALWAYS remember to initialize al your code.

2) Yes, you can send in literal values, you don''t have to create variables to send to your constructor.

3) You should use initializer lists instead :

class MyClass {
private;
int i;
float f;
public:
MyClass(int _i, float_f) : i(_i), f(_f) { }
};

This is conceptually the same as

MyClass(int _i, float_f) {
this->i = _i;
this->f = _f;
}

but it means your variables inside the class are only set to a value once (it becomes more useful for non-primitive types).

The benefit of initializing things in a constructor are obvious:

- you localize all your initialization code
- you can''t "forget" to initialize some part of your object

Regards,
Jeff


[ Little Devils Inc. ]

Share this post


Link to post
Share on other sites
You should always initilize every data member of the class in your constructor. There is, however, a shorthand way to do some of the initilization.


// somewhere in the header file
Player(); // prototype

// somewhere in the CPP file

// constructor for player class
Player():health(20), mana(30), stmina(100)
{
}


the : after the closing parenthesis tells the compiler that you are going to set values of the data members using the syntax...

variable(value)

The only think you cannot do with the : is allocate memory dynamicly. You should use this technique whenever possible because the compiler will optimize the value copying for you.


Now about passing paramiters to the constructor. There is a nifty trick you can use to make your function look like it isn''t taking parameters. In your prototype, set the parameters equal to the value you want them to be.


// somewhere in the header file
Player(int h=20, int m=30, int s=100);

// somewhere in the CPP file
Player(int h, int m, int s):health(h), mana(m), stamina(s)
{
}





Share this post


Link to post
Share on other sites
If your class has some default values that could be assigned, but you also want to be able to pass in parameters, you can just overload the constructor, like so:


//Player.h

class Player
{
public:
Player();
Player(int Health, int Mana, int Stamina);
Player(const std::string& File);
Player(const Player& OrigPlayerCopy);
};
//

//Player.cpp

Player::Player()
{
mHealth = DEFAULT_HEALTH;
mMana = DEFAULT_MANA;
mStamina = DEFAULT_STAMINA;
}
Player::Player(int Health, int Mana, int Stamina)
{
mHealth = Health;
mMana = Mana;
mStamina = Stamina;
}
Player::Player(const std::string& File)
{
//open file, get health, mana, stamina from that file

}
Player::Player(const Player& OrigPlayerCopy)
{
mHealth = OrigPlayerCopy.mHealth;
mMana = OrigPlayerCopy.mMana;
mStamina = OrigPlayerCopy.mStamina;
}


That way, you have multiple different ways to create a new player. The first is the default constructor. If you define other constructors, but don''t define the default constructor, then certain things won''t work with your class, such as static arrays of the class. (If you define no constructors at all, then a default is made for you automatically.)

The second and third are custom constructors that allow you to specify where the constructor will get the initialization values, whether it be directly from parameters, or by looking them up in a file, etc.

The fourth is another special constructor, like the first. It''s a copy constructor. It is used whenever an object of this class is being copied directly to another object of this same class, usually through the = operator. A basic copy constructor is defined for you, if you don''t make one yourself, but it just does a basic copy of all of the members. If you have pointers in your class, then it will just copy the value of the pointers, which could lead to serious problems. In those cases, you should probably make your own copy constructor.

Share this post


Link to post
Share on other sites
for the second one it should be

Player::Player(int Health, int Mana, int Stamina): mHealth(Health), mMana(Mana), mStamina(Stamina)
{
}


always prefer this syntax to doing the inits inline, it even works for structs passed in by refence (and i assume referenced passed objects with copy constructors, not that i''ve tried)

The reason isnt so much to do with the compiler optermining the assignment but todo with how things are inited.

With the version above, when you create the varible on class construction it is assigned the varible passed to it (in the instance of a class or a struct the copy constructor is invoked)

Now, if its done like this :

Player::Player(int Health, int Mana, int Stamina)
{
mHealth = Health;
mMana = Mana;
mStamina = Stamina;
}


First the vars are created (and in the case of objects the default constructor is invoked), then we get into the constructor its self and the assignment operator is called to assign the values to the vars (be they ints or objects)
As you can see, this is a potentialy very wasteful extra step and should be avoided if at all possible.

Share this post


Link to post
Share on other sites
quote:
Original post by Onemind
You should always initilize every data member of the class in your constructor. There is, however, a shorthand way to do some of the initilization.


// somewhere in the header file
Player(); // prototype







thanks for your help (everyone else too!) , but i dont understand what this part is. what do you mean by prototype? what is this here for, and why would it go in a header? is this here just so your other classes can use this class?

also, im a little confused with the example palidine showed me
where the contructor looks like this


Player::Player(int health = DEFAULTNUMBER, int mana = DEFAULT NUMBER2, int stamina = DEFAULTNUMBER3)
{
this->health = health;
this->mana = mana;
this->stamina = stamina;
}


could someone explain whats going on behind the scenens for this example? this looks like the one i like the most, and yes onemind i realize you did the same thing only shorthand, but i want to take one step at a time . anyway, so basically, with this contructor, you could call it by either doing

Player playerone(); //this will do the default numbers???

or you could do

Player playerone(20,30,100);

this will load 20 30 and 100 into health/stamina/mana??? if im wrong, could you show me how to declare a object of the player class if im using this^^^^ contructor???

thank you for all your help!!!


Share this post


Link to post
Share on other sites
Yes, a prototype is needed in the header so that other files can use your class. [Edit - Unless everything is in the header, and thus most likely inlined. Either way, other files need to know the form of your class, and its member functions, including the constructor, and they are told what its form is by #include-ing the header file, which should contain all relavent information.]

As for calling a function with default values, you can specify none of them, all of them, or even just the first n parameters. For example, all of these should be fine:

Player playerone();
Player playerone(20);
Player playerone(20, 30);
Player playerone(20, 30, 100);

If a parameter isn't specified, it's default value is taken. But if I remember right, you only specify the default value in the prototype, if you have both a prototype and a declaration.

And as for using the initializer list over just putting the initializations into the body of the constructor, I have learned to do it the correct way (thanks to GameDev, actually), but it's not a habit yet. I apologize for suggesting the obviously less acceptable form.

[edited by - Agony on February 20, 2004 2:41:17 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Agony
Yes, a prototype is needed in the header so that other files can use your class. [Edit - Unless everything is in the header, and thus most likely inlined. Either way, other files need to know the form of your class, and its member functions, including the constructor, and they are told what its form is by #include-ing the header file, which should contain all relavent information.]

As for calling a function with default values, you can specify none of them, all of them, or even just the first n parameters. For example, all of these should be fine:


Player playerone();
Player playerone(20);
Player playerone(20, 30);
Player playerone(20, 30, 100);

If a parameter isn't specified, it's default value is taken. But if I remember right, you only specify the default value in the prototype, if you have both a prototype and a declaration.

And as for using the initializer list over just putting the initializations into the body of the constructor, I have learned to do it the correct way (thanks to GameDev, actually), but it's not a habit yet. I apologize for suggesting the obviously less acceptable form.

[edited by - Agony on February 20, 2004 2:41:17 PM]



thanks for the response, just one last question :


Player playerone(); //will init all default values

Player playerone(20); //will init first value to 20 and the other 2 will be default???

Player playerone(20, 30); //ill init first 2 and the other will be default???

Player playerone(20, 30, 100); //init all to these 3 values, dont use any default




so am i right? and what if i want to init the last 2 or 3 but want the first one by default. not possible? thanks for your help!!!






[edited by - graveyard filla on February 20, 2004 4:08:55 PM]

[edited by - graveyard filla on February 20, 2004 4:09:14 PM]

[edited by - graveyard filla on February 20, 2004 4:09:29 PM]

[edited by - graveyard filla on February 20, 2004 4:09:55 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by graveyard filla

Player playerone(); //will init all default values
Player playerone(20); //will init first value to 20 and the other 2 will be default???
Player playerone(20, 30); //ill init first 2 and the other will be default???
Player playerone(20, 30, 100); //init all to these 3 values, dont use any default
so am i right?

Correct.
quote:
and what if i want to init the last 2 or 3 but want the first one by default. not possible?

Correct, it isn''t possible, unfortunately. Other languages can do this, but depending on how it''s implemented, it can cause function calls to be less efficient, and C++ strives for efficiency. Although I do remember in VB you can say Method(, 5, 3, , 4) and those empy parameters, indicated by the blank commas, will be filled in with default values, and it seems that a compiler could make that just as efficient as what C++ does. But C++ won''t do this.

Share this post


Link to post
Share on other sites