Skip to main content
gamedev.net
🔒 Locked

Constructor Problems

Started by guitarstar26 9 replies 1.8k views
Original Post
guitarstar26
guitarstar26
Hello, I am having problems with one of my class' constructor.

Here is the class:
class friendly : public unit{public:	int strength;	int reflex;	int speed;	int endurance;	int smarts;	int perception;	double carried;	int healthPointsMax;	//Derived	double carryingCapacity;//Derived	vector<weapon> vwTable;	vector<ammo> vaTable;	weapon equippedMain;	weapon equippedPistol;	weapon equippedGrenade;	//Functions	friendly();	friendly(string n, int str, int ref, int spd, int end, int smrt, int per);};


Here is the constructor code:
friendly::friendly(string n, int str, int ref, int spd, int end, int smrt, int per){	name = n;	strength = str;	reflex = ref;	speed = spd;	endurance = end;	smarts = smrt;	perception = per;	healthPoints = end*2+10;	healthPointsMax = end*2+10;	goPoints = 20+spd+end/2;	blitz = spd/2;	carryingCapacity = str*5+15;	thrownAttack = str+per/2;	thrownDefense = ref+smrt/2;	meleeAttack = str+smrt/2;	meleeDefense = ref+per/2;	rangedAttack = smrt+ref/2;	rangedDefense = per+str/2;	carried = 0;	equippedMain = noweapon;    //THIS IS	equippedPistol = noweapon;  //THE	equippedGrenade = noweapon; //PROBLEM	isFriendly = true;}


The problem is that equippedMain and the other equipped variables are not being set to noweapon.

weapon is another class and noweapon is an instance of that class. noweapon has an overloaded equality operator. When I use breakpoints it shows that noweapon has all blanks for all it's members. This is incorrect and it should have "none" for it's name member. I have also tried other weapons and that doesn't work either.

What am I missing?

PS if you need the code for weapon or it's operator= function let me know.

PPS Why do all the '+' signs get erased in the [ source ] tags?
Nevermind, I guess it's only in "Preview" mode.
guitarstar26
guitarstar26
class weapon : public item{public:	string ammoType;	int normMinDam;	int normMaxDam;	int critMinDam;	int critMaxDam;	int clipSize;	int range;	double fireSpeedMod;	double reloadSpeedMod;	char classification[80];	char trainingType[80];	weapon();	weapon(string n, string a, int nMin, int nMax, int cMin, int cMax, int csize, double w, int r, double fSM, double rSM, char classif[], char trainType[]);	weapon::weapon(const weapon &w);	weapon& weapon::operator=(const weapon& w); 	bool weapon::operator==(const weapon& w);};


weapon::weapon(string n, string a, int nMin, int nMax, int cMin, int cMax, int csize, double w, int r, double fSM, double rSM, char classif[], char trainType[]){	name = n;	ammoType = a;	normMinDam = nMin;	normMaxDam = nMax;	critMinDam = cMin;	critMaxDam = cMax;	clipSize = csize;	weight = w;	range = r;	fireSpeedMod = fSM;	reloadSpeedMod = rSM;	strcpy(classification, classif);	strcpy(trainingType, trainType);	type = "";}

weapon& weapon::operator=(const weapon& w) {    if(this == &w)		return *this;    name = w.name;	ammoType = w.ammoType;	normMinDam = w.normMinDam;	normMaxDam = w.normMaxDam;	critMinDam = w.critMinDam;	critMaxDam = w.critMaxDam;	clipSize = w.clipSize;	weight = w.weight;	range = w.range;	fireSpeedMod = w.fireSpeedMod;	reloadSpeedMod = w.reloadSpeedMod;	strcpy(classification, w.classification);	strcpy(trainingType, w.trainingType);    return *this;}


I define noweapon in weapon.h as

extern noweapon;

then initialize it in weapon.cpp as
weapon noweapon ("None","",1,5,6,8,0,0,0,0,0,"","");
Black Knight
Black Knight
Put a breakpoint inside the weapon constructor and see if noweapon is initialized properly. Also I wouldn't use char arrays and strcpy as it makes it easy to mess up with memory. Any reason why you are not using std::stirng?

guitarstar26
guitarstar26
The char arrays were there from before when I was less comfortable with using strings. I am in the process of switching everything over so VS stops yelling at me about strcpy being unsafe.

If I explicitly do
friendly brian("Brian", 3, 3, 3, 3, 3, 3);brian.equippedMain = noweapon;


Then brian has the correct data in equippedMain;

I put a breakpoint in the weapon constructor and noweapon is being initialized.

Is it possible that the code is being run out of order, for a lack of better term.

Could the code for constructing the friendly be running before noweapon gets constructed?

Also, could the inheritance from item be a problem for weapon?
Name and a few other members are inherited from item into weapon.

When I create a weapon, does the constructor for item have any effect? (I currently have no explicit constructor for items)
Black Knight
Black Knight
When you inherit from a class the constructor for the base class is called before the constructor of the derived class. If you don't have an explicit one the compiler should create a default one.

How is the friendly class created? Is it a global like noweapon?
guitarstar26
guitarstar26
Yes. It is defined in friendly.h
extern friendly brian;

and initialized in friendly.cpp
friendly brian("Brian", 3, 3, 3, 3, 3, 3);




[Edited by - guitarstar26 on September 5, 2010 1:20:15 AM]
Black Knight
Black Knight
Yea that might be the problem put two breakpoints one inside friendly constructor and one inside weapon and see which one is getting called first.

If friendly is getting called first then noweapon is not instantiated yet.

You might want to consider your design and make thing members of classes and pass them as parameters by reference etc. instead of making everything global.
guitarstar26
guitarstar26
Yes, the constructor for friendly is being called first.

Here is a temporary fix.
friendly.cpp - constructor
friendly::friendly(string n, int str, int ref, int spd, int end, int smrt, int per){	name = n;	strength = str;	reflex = ref;	speed = spd;	endurance = end;	smarts = smrt;	perception = per;	healthPoints = end*2+10;	healthPointsMax = end*2+10;	goPoints = 20+spd+end/2;	blitz = spd/2;	carryingCapacity = str*5+15;	thrownAttack = str+per/2;	thrownDefense = ref+smrt/2;	meleeAttack = str+smrt/2;	meleeDefense = ref+per/2;	rangedAttack = smrt+ref/2;	rangedDefense = per+str/2;	weapon noweapon	("None","",0,0,0,0,0,0,0,0,0,"","");	carried = 0;	equippedMain = noweapon;	equippedPistol = noweapon;	equippedGrenade = noweapon;	isFriendly = true;}


How would I redesign to avoid this problem, other than the quick fix above?
I'm unsure what you mean by "make things members of classes and pass them as parameters by reference etc. instead of making everything global."

Black Knight
Black Knight
Instead of creating globals you will have friendly a member of another class, like a map class or any other class which makes sense. Then when you are about to create a friendly instance you can create it like this without using any globals. Lets assume friendly instances are stored in a std::vector inside a Map class.

class Map
{
public:
std:vector<friendly> friendly_list;

void addFriendly(const std::string& name,other params etc.)
{
weapon noweapon('params',...);

friendly newFriendly(name,...);

friendy_list.push_back(friendly);
}

}
Zahlman
Zahlman
You know... you are holding the weapon instances by value, so you are going to have to make multiple copies anyway. So having a 'blank' instance to copy from is not really that useful.

The simple thing would be to either define the default constructor for the weapon class so that it creates "no weapon", or to have a free function no_weapon() which returns a non-weapon.

Also:

- Have you heard of initialization lists?

- Once you are using std::string for text you won't be needing that ugly operator=. Get this fixed ASAP please. :)

- Don't store "derived" statistics. Whenever the base values change, you'll have to update every derived statistic that depends on them, and you're bound to forget something or drive yourself crazy maintaining all the logic for it. Instead, use member functions which calculate and return the derived statistic.

- That also holds for 'isFriendly'. You can put a virtual bool isFriendly() in the base, and define it to return true in friendly, and false in enemy. Or you could use dynamic_cast<>.

Or you could figure out whether you actually need separate types for friendly and enemy units. Don't they have the same stats / play by the same rules?

- On the other hand, why not have actual separate types for different weapons? What kinds of weapon do you have? What kinds of weapon can 'equippedMain', 'equippedPistol' and 'equippedGrenade' be?

Topic Locked

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

Sign in to reply to this topic.