Archived

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

How can I make it so that I can use the appropriate constructor for a type of...

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

player and still be able to use methods. I have a CPlayer class and a Barbarian class and a Necromancer class. I want the person to be able to choose which type they want to be. I tried to use...
void main(){
    int chartype;
    cout<<"1 barbarian , 2 necromancer";
    cout<<"Pick a type:";
    cin>>chartype;
    if(chartype == 1){
         Barbarian player;
    }
    else{
         Necromancer player;
    }
But then when i want to use a method it gives me errors... Is there a way to make it so I can do this... Here''s the full source code.
//Copyright 2003 Cory Fisher

#include<iostream>								//For cin,cout

#include<string>								//For string use

#include<stdio.h>								//For standard io

using namespace std;							//Dont know why just everyone says you should

string nameSet();								//Forward declaration of nameSet()

class CMonster;
class CPlayer;
class Barbarian;
class Necromancer;
class CPlayer{									//Base Player Class

private:
	int playerHealth;							//Begin of self explanatory section

	int playerMaxHealth;						
	int playerMana;								
	int playerMaxMana;							
	int playerLevel;							
	int playerStrength;			
	int playerSpeed;
	int playerDefense;
	int playerSkill;
	string playerName;
	string playerClass;							//End of self explanatory section

public:
	string skill[10];
	CPlayer():									
		playerHealth(0),						
		playerMaxHealth(0),
		playerMana(0),
		playerMaxMana(0),
		playerLevel(1),
		playerStrength(0),
		playerSpeed(0),
		playerDefense(0),
		playerSkill(1),
		playerName(""),
		playerClass("")
	{
	}
	int getHealth(){							//Begin Self Explanatory

		return playerHealth;
	}
	int getMaxHealth(){
		return playerMaxHealth;
	}
	int getMana(){
		return playerMana;
	}
	int getMaxMana(){
		return playerMaxMana;
	}
	int getLevel(){
		return playerLevel;
	}
	int getStrength(){
		return playerStrength;
	}
	int getSpeed(){
		return playerSpeed;
	}
	int getDefense(){
		return playerDefense;
	}
	int getSkill(){
		return playerSkill;
	}
	string getName(){
		return playerName;
	}
	string getClass(){
		return playerClass;
	}
	void setHealth(int newhealth){
		playerHealth = newhealth;
	}
	void setMaxHealth(int newmaxhealth){
		playerMaxHealth = newmaxhealth;
	}
	void setMana(int newmana){
		playerMana = newmana;
	}
	void setMaxMana(int newmaxmana){
		playerMaxMana = newmaxmana;
	}
	void setLevel(int newlevel){
		playerLevel = newlevel;
	}
	void setStrength(int newstrength){
		playerStrength = newstrength;
	}
	void setSpeed(int newspeed){
		playerSpeed = newspeed;
	}
	void setDefense(int newdefense){
		playerDefense = newdefense;
	}
	void setSkill(int newskill){
		playerSkill = newskill;
	}
	void setName(string newname){
		playerName = newname;
	}
	void setClass(string newclass){
		playerClass = newclass;
	}												//End of Self Explanatory

	void printBaseInfo(){							//Prints the things that are common to all characters

		cout<<"Name: "<<playerName<<endl;
		cout<<"	Level: "<<playerLevel<<endl;
	}
	void printSkills(){								//Prints all skills known

		cout<<"Skills Learned: ";
		for(int i = 1; i < 11; i++){
			if(playerSkill < i){
				break;
			}
			if(playerSkill > i){
					cout<<skill[i]<<", ";
			}
			if(playerSkill == i){
				cout<<skill[i]<<endl;
			}

		}
	}
	void attack(CMonster *monster);

};
class Barbarian : public CPlayer{					//Derived barbarian class

public:
	Barbarian(){									//Default constructor set to what i like for a Barbarian

		setHealth(100);
		setMaxHealth(100);
		setMana(20);
		setMaxMana(20);
		setStrength(60);
		setSpeed(40);
		setDefense(60);
		setName(nameSet());
		setClass("Barbarian");
		initSkills();
	}
	void printInfo(){							   //Prints not always same stuff as other characters.

		system("cls");
		cout<<"Class: "<<getClass()<<endl;
		printBaseInfo();
		cout<<"	Health: "<<getHealth()<<"/"<<getMaxHealth()<<endl;
		cout<<"	Mana: "<<getMana()<<"/"<<getMaxMana()<<endl;
		cout<<"	Strength: "<<getStrength()<<endl;
		cout<<"	Speed: "<<getSpeed()<<endl;
		cout<<"	Defense: "<<getDefense()<<endl;
		printSkills();
	}
	void initSkills(){							//Initialize barbarians skills

		skill[0] = "Bruise";
		skill[1] = "Bash";
		skill[2] = "Crush";
		skill[3] = "Bang";
		skill[4] = "Break";
		skill[5] = "Boom";
		skill[6] = "Crack";
		skill[7] = "Shatter";
		skill[8] = "Destroy";
		skill[9] = "Annihilate";
	}

};
class Necromancer : public CPlayer{				//Derived necromancer class

public:								
	Necromancer(){								//Default constructor stats i want for a necromancer

		setHealth(100);
		setMaxHealth(100);
		setMana(60);
		setMaxMana(60);
		setStrength(20);
		setSpeed(60);
		setDefense(40);
		setName(nameSet());
		setClass("Necromancer");
		initSkills();
	}
	void printInfo(){							//Same as above

		system("cls");
		cout<<"Class: "<<getClass()<<endl;
		printBaseInfo();
		cout<<"	Health: "<<getHealth()<<"/"<<getMaxHealth()<<endl;
		cout<<"	Mana: "<<getMana()<<"/"<<getMaxMana()<<endl;
		cout<<"	Strength: "<<getStrength()<<endl;
		cout<<"	Speed: "<<getSpeed()<<endl;
		cout<<"	Defense: "<<getDefense()<<endl;
		printSkills();
	}
	void initSkills(){							//Same as above cept its for necromancer

		skill[0] = "Fire";
		skill[1] = "Flame";
		skill[2] = "Burn";
		skill[3] = "Big Burn";
		skill[4] = "Blaze";
		skill[5] = "Firestorm";
		skill[6] = "Forest Fire";
		skill[7] = "Flame of Demon";
		skill[8] = "Smoke Rings";
		skill[9] = "Hell Fire";
	}
};
class CMonster{
private:
	int health;
	int maxhealth;
	int defense;
	int speed;
	int strength;
public:
	CMonster(){
		health = 100;
		maxhealth = 100;
		defense = 100;
		speed = 100;
		strength = 100;
	}
	int getMonsterHealth(){
		return health;
	}
	void setMonsterHealth(int newhealth){
		health = newhealth;
	}
	int getMonsterDefense(){
		return defense;
	}
}big;
int chartype;
void getCharacterType(){									
	cout<<"1) Barbarian\n";
	cout<<"2) Necromancer\n";
	cout<<"What kind of character would you like to be?";
	cin>>chartype;
}

void main(){									//Main Does nothing haven''t started actual game coding yet

	getCharacterType();
	if(chartype == 1){
		Barbarian player;
	}
	else{
		Necromancer player;
	}
	cout<<player.getStrength();
}
string nameSet(){								//It gets the name from the user when the constructor for 

	string charname;							//the class is called;

	cout<<"Enter a name:";
	cin>>charname;
	return charname;
}		
void CPlayer::attack(CMonster *monster){
	monster->setMonsterHealth((monster->getMonsterHealth() + (.050 * monster->getMonsterDefense())) - (getStrength()));
}
The error is player not defined... I hate asking so many questions but I couldn''t find out this information anywhere else. Thanks yet again.
Favorite Quotes:Gandalf: You shall not pass!|Smeagol: We don''t need you!|Sloth: Hey you guys!|

Share this post


Link to post
Share on other sites
A couple of things going on here:

1. When you declare a variable within a block (between two braces), it is only valid within the block. Like so:


if(a)
{
int b;
print(b); // can use it here!

{
print(b); // here, too!

}
}
print(b); // ERROR-- can't use it here!


2. A particular name in a particular scope can only refer to one datatype. It's one or the other. HOWEVER, if Barbarian and Necromancer inherit from a common base class, you can use virtual functions on a pointer to that base class to accomplish much the same thing. Read up on virtual functions in your C++ book.


How appropriate. You fight like a cow.

[edited by - sneftel on November 6, 2003 11:10:57 PM]

Share this post


Link to post
Share on other sites
you can use inheritence


class Player
{
// Common player functions

};

class Barbarian : public Player
{
};

class Necromancer : public Player
{
}

void main()
{
Player* p = 0;
if( /* choice one*/ )
p = new Barabarian();
else
p = new Necromancer();
}


You''ll have toput all the methods you want to use in the Player base class and then if you need different functionality for different classes, you can re-impliment them in the derived classes. read up on the keyword ''virtual''


:::: [ Triple Buffer ] ::::

Share this post


Link to post
Share on other sites
First of all, since you''re declaring the variable player in an if statement, it goes out of scope once you hit the end of the block.

Secondly, you need a pointer to the base class in order to use all of the common functions when you don''t know what type of player they will choose.


CPlayer *player = 0;

if(chartype == 1)
{
player = new Barbarian();
}
else
{
player = new Necromancer();
}

cout << player->getStrength();

if (player != 0)
delete player;

Share this post


Link to post
Share on other sites
The problem is in the scope of the local variable. When you have an if statement, and declare a variable inside a block (surrounded by braces), that variable is only valid inside the block. For example:

if (WorldIsFlat)
{
bool ColumbusWasWrong = true;
}

if (ColumbusWasWrong) // Compile error here!

When a variable is declared inside a block, it cannot be referenced outside the block.

You could have a CPlayer pointer, and have the different player variables declared outside the block, and then point the CPlayer to the appropriate variable. Or, do a ''new'' to create either of the player objects depending on the choice:


CPlayer *player;
if (chartype == 1)
player = new Barbarian();
else
player = new Necomancer();

// Use player

delete player;

Share this post


Link to post
Share on other sites
To begin with, static variables exist only in the block of code they are defined in.

e.g.

{
int i;
}

i = 8; // compiler error

So you'll need polymorphism, basically


CPlayer* player;
// get choice, then
player = new Barbarian;
// or
player = new Necromancer;

This will be hard to use if you haven't learnt pointers and polymorphism, if you/when you have, it'll be easy.

Keep at it.

PS. I think there is a good tute at www.gametutorials.com

EDIT: Beaten to it 4 times!

Wizza Wuzza?

[edited by - Chris Hare on November 6, 2003 11:19:17 PM]

[edited by - Chris Hare on November 6, 2003 11:21:02 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Chris Hare
To begin with, static variables exist only in the block of code they are defined in.
Hrmph... while that is kindof true, noone have spoken about static variables. One could claim that statics, as opposed to non-statics, do exist outside the block they are defined in. You may have meant local variables, though.

Share this post


Link to post
Share on other sites
Well, first of all, when you declare a variable, you can only use it in that sc--

oh. I already replied. Nevermind.


How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
'But then when i want to use a method it gives me errors... Is there a way to make it so I can do this...'

What are your exact errors?

I think you need to ask yourself if inheritence is really needed for your game. You could implement just the 'CPlayer' class and instead of using a derived class to initialize all of the member variables, just make a function for each player class that initializes the variables to the proper values.

It would make things a lot simpler for you at the moment. Sometimes it's far better to have a completed project that may not be the most technical piece of work, than to have a technically complex project which you never get to work.

Edit: Maybe go one step further an just turn the CPlayer class into a struct. Since you're exposing all of the private class data via get and set methods, you're not really achieving any sort of true data encapsulation. You can still use a constructor with a struct to initialize default values if you need to, but even that could be avoided.


[edited by - SysOp_1101 on November 6, 2003 11:44:02 PM]

Share this post


Link to post
Share on other sites
quote:

quote:
--------------------------------------------------------------------------------
Original post by Chris Hare
To begin with, static variables exist only in the block of code they are defined in.
--------------------------------------------------------------------------------

Hrmph... while that is kindof true, noone have spoken about static variables. One could claim that statics, as opposed to non-statics, do exist outside the block they are defined in. You may have meant local variables, though.



Sorry, I meant ''statically created'' object, as opposed to dynamically with new / malloc, not as in the C++ keyword.



Wizza Wuzza?

Share this post


Link to post
Share on other sites
The Factory Method Design Pattern is exactly what you need here. Dont be discouraged by the fancy name, its just a tried and true method for doing pretty much exactly the type of thing you want. You should be able to find info about it on google, understand said info, and be able to start coding in about 30-60 min. Its well worth the effort to look in to it, because you''ll probably use this pattern for (almost) every other project you ever make.

Share this post


Link to post
Share on other sites
Read up a little more on the syntax of the language, paying particulary close attention to the section on VARIABLE SCOPE, as many people here have pointed out. Don''t pay attention to the people talking about inheritance or class factories. That''s not what you need to learn about right now. Walk before you run.

Share this post


Link to post
Share on other sites
Where is the error occuring? Is your intent to learn more about C++ and classes? Is that why you''re using them for different players? If not, then I would try to make the player a single class, and just use some switch statements for different types of characters. If that is your intent, I would learn the smallest amount about virtual functions and inheritance that''s possible. In other words, stop reading once you know how to get passed your problem.

Jiia

Share this post


Link to post
Share on other sites
I am really amused by all the replies. Funny all of them advocate inheritence to the solution of your problem, when composition is a better solution. Inheritence is a compile time determined, and is limited by as many as you implement. For example, a sage who is a mage and cleric, a paladin who is a cleric and warrior. There are 6 classes involved here, not to mention they would need to all derive from a single Player class. (Multiple inheritence when dealing with a common base class, also known as the dread diamond inheritence is tricky unless you know how to handle it). So that''s a total of seven class.

Consider however, this. An abstract CharacterClass class interface is defined(some could call this a policy). It can hold another instance of CharacterClass, or you can have the Player class holds two instance of CharacterClass. This class will define non-instance specific manipulations(though it can perhaps hold information of skill levels, or other ''class specific information'', not ''player specific information'' like hp, mp, etc). Thus, in order to create a Player class, you can create an instance of a Player, then aggregate a Cleric and a Fighter CharacterClass. So you are building new classes out of existing class. In fact, you''re reusing codes. Not doing massively copy and paste that *might* occur.

A better example could be expressed in terms of monster. Some people might suggest an abstract Monster base class. And then you get Flying Monster, Sea Monster, Land Monster derived. Then you furthur derive each type into Smart, Dumb and Average monster. That''s a total of 9 classes eventually, AND 3 in the middle, PLUS a base. Now, what happens if you decide that each monster can furthur be catagorized to friendly and hostile monsters? You get another 18 classes to implement. The BETTER solution is to identify and break the abstract monster into these composotion. The abstract monster will hold a Type class(identify if it can fly, swim, or just walk), and its intelligence(smart, dumb or average), and then friendliness(hostile or friendly). So you end up with 3 type classes, 3 intelligence classes, 2 friendliness classes, and a generic monster class. That''s a total of 9 classes that can produce the same effect as 18+9+3+1=31 classes created by inheritence!

Do not blindly follow and think inheritence is the solution Most times, it is not. Compostion, runtime or compile time, is almost always a better solution.

*note, almost, though i would champion it as the solution in this particular case*
*and note, i was suggesting runtime compostion. You could go with compile time compostion via templates, but you end up with far more possibility, plus other issues I do not wish to go into because they require another discussion on problem face and needed solutions*

Share this post


Link to post
Share on other sites