Setting struct variable in class object parameter list

I am just writing and playing around with some code and I wanted to have a word represent a number in the parameter list of my class object, my numbers are ints but if i wanted to use a float then I wouldn't be able to use an enum, so I created a struct and then initialized the variable in the parameter lists to keep things neater. Im wondering if this is ok to do. Everything works just fine but i've learned over the years that doesn't always mean it's correct practice.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Character
{
public:
	Character(string charClass, int charHealth, int charMaxHealth, int charAttackPwr, int charMaxAttackPwr) :
		charClass(charClass),
		charHealth(charHealth),
		charMaxHealth(charMaxHealth),
		charAttackPwr(charAttackPwr),
		charMaxAttackPwr(charMaxAttackPwr) {}

	string GetCharClass() { return charClass; }

	int GetCharHealth() { return charHealth; }
	int GetCharAttackPwr() { return charAttackPwr; }
	int GetCharMaxAttackPwr() { return charMaxAttackPwr; }
	int GetCharMaxHealth() { return charMaxHealth; }

	void DealDamage(int damageDealt);
	void TakeDamage(int damageTaken);
	void RestoreHealth(int restoreAmount);
	void UpgradeAttackPower(int upgradeAmount);
	void DisplayCharacterInfo(Character& character);

private:
	string charClass{};
	int charHealth{};
	int charMaxHealth{};
	int charAttackPwr{};
	int charMaxAttackPwr{};
};


ostream& operator<< (ostream& os, Character& character)
{
	os << "Class Name: " << character.GetCharClass() << endl;
	os << "Health: " << character.GetCharHealth() << endl;
	os << "Max Health: " << character.GetCharMaxHealth() << endl;
	os << "Attack Power: " << character.GetCharAttackPwr() << endl;
	os << "Max Attack Power: " << character.GetCharMaxAttackPwr() << endl;

	return os;
}

void Character::RestoreHealth(int restoreAmount)
{
	if (charHealth < GetCharMaxHealth())
	{
		if (restoreAmount < charHealth)
		{
			charHealth += restoreAmount;
		}
		if (restoreAmount > charHealth)
		{
			charHealth = GetCharMaxHealth();
		}
	}
	else
	{
		cout << "Player health is full!" << endl;
	}
}

void Character::DisplayCharacterInfo(Character& character)
{
	cout << character << endl;
}


//Create a struct to give values a name instead of just a confusing number. 
//Could have used an enum, but enums cant contain floats, so this fixes that potential issue.
struct Data
{
	int health{};
	int maxHealth{};
	int attackPower{};
	int maxAttackPower{};
};


int main()
{
	Data data;

	Character Knight("Knight", data.health = 100, data.maxHealth = 150, data.attackPower = 50, data.maxAttackPower = 50);
	Character Samurai("Samurai", data.health = 50, data.maxHealth = 70, data.attackPower = 300, data.maxAttackPower = 300);
	Character Marine("Marine", data.health = 200, data.maxHealth = 250, data.attackPower = 100, data.maxAttackPower = 120);

	vector<Character> charList;

	charList.push_back(Knight);
	charList.push_back(Samurai);
	charList.push_back(Marine);

	for (int i = 0; i < charList.size(); i++)
	{
		cout << charList[i] << endl;
	}


	//Debug
	cout << "--DEBUG--\n" << endl;

	Samurai.RestoreHealth(36);
	Samurai.DisplayCharacterInfo(Samurai);

	Knight.RestoreHealth(49);
	Knight.DisplayCharacterInfo(Knight);

	cout << "--DEBUG--" << endl;
	//End Debug

	return 0;
}
Last edited on
It's all very vague. Especially considering that there is neither an enum nor float anywhere in your code.

Your use of Data doesn't make sense. What are you trying to achieve?

I suggest that you make the characters on line 89 to 91 const. For instance on line 108 you modify the Samurai object, but it has no effect to anything in charList because it is a copy.
It's all very vague. Especially considering that there is neither an enum nor float anywhere in your code.


Right, but what im saying is if I ever wanted to change my ints to a float, or if i add a non int value like a float, then I would have to completley rewrite the code as enums cant be used with floats. what I want is instead of doing this:

Character Knight("Knight", 100, 150, 50, 50);

Which is vague because what do those numbers mean? at first glance you have no idea, so you have to go to the class and look it up, or count on intellisense to show you what the variables names are when you hover inside the parameter list, so I did this:

Character Knight("Knight", data.health = 100, data.maxHealth = 150, data.attackPower = 50, data.maxAttackPower = 50);

This is far clearer and when you look at it you know what value is associated with a certain part of the character, like health and attack etc.

The struct doesnt really do anything other than provide a name for that variable. Basically a stand in for an enum so the values can have a clear name so when you look at the object parameter list, you know what the values are.

My main question is, is it ok to set the variable inside the parameter list of the object. Because normally you just define the variable then pass the variable name into the parameter list, but i'm defining the variable inside the parameter list, and want to know if that creates any issues.

I suggest that you make the characters on line 89 to 91 const. For instance on line 108 you modify the Samurai object, but it has no effect to anything in charList because it is a copy.
This is far clearer and when you look at it you know what value is associated with a certain part of the character, like health and attack etc.
This would certainly make most coders cringe...

but i'm defining the variable inside the parameter list
Nope, you don't. You define the variable data on line 88. In the parameter list you just assign some values to the members.

It may have some minor documentary value not more.

How about some completely error proof parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <string>
#include <vector>

using namespace std;

template<typename tag, typename value_type>
struct parameter_type
{
    value_type m_Value;
    explicit parameter_type(const value_type& val) : m_Value{val}
    {
    }
};

namespace health
{
    using value_type = float;
    namespace start
    {
        struct tag {};
        using type = parameter_type<tag, value_type>;

        const type Knight{100};
    }
    namespace max
    {
        struct tag {};
        using type = parameter_type<tag, value_type>;

        const type Knight{150};
    }
}

class Character
{
public:
	Character(string charClass, const health::start::type& charHealth, const health::max::type& charMaxHealth, int charAttackPwr, int charMaxAttackPwr) :
		charClass(charClass),
		charHealth(charHealth.m_Value),
		charMaxHealth(charMaxHealth.m_Value),
		charAttackPwr(charAttackPwr),
		charMaxAttackPwr(charMaxAttackPwr) {}

	string GetCharClass() { return charClass; }

	health::value_type GetCharHealth() const { return charHealth; }
	int GetCharAttackPwr() { return charAttackPwr; }
	int GetCharMaxAttackPwr() { return charMaxAttackPwr; }
	health::value_type GetCharMaxHealth() const { return charMaxHealth; }

	void DealDamage(int damageDealt);
	void TakeDamage(int damageTaken);
	void RestoreHealth(int restoreAmount);
	void UpgradeAttackPower(int upgradeAmount);
	void DisplayCharacterInfo(Character& character);

private:
	string charClass{};
	health::value_type charHealth{};
	health::value_type charMaxHealth{};
	int charAttackPwr{};
	int charMaxAttackPwr{};
};


ostream& operator<< (ostream& os, Character& character)
{
	os << "Class Name: " << character.GetCharClass() << endl;
	os << "Health: " << character.GetCharHealth() << endl;
	os << "Max Health: " << character.GetCharMaxHealth() << endl;
	os << "Attack Power: " << character.GetCharAttackPwr() << endl;
	os << "Max Attack Power: " << character.GetCharMaxAttackPwr() << endl;

	return os;
}

void Character::RestoreHealth(int restoreAmount)
{
	if (charHealth < GetCharMaxHealth())
	{
		if (restoreAmount < charHealth)
		{
			charHealth += restoreAmount;
		}
		if (restoreAmount > charHealth)
		{
			charHealth = GetCharMaxHealth();
		}
	}
	else
	{
		cout << "Player health is full!" << endl;
	}
}

void Character::DisplayCharacterInfo(Character& character)
{
	cout << *this character << endl;
}


//Create a struct to give values a name instead of just a confusing number. 
//Could have used an enum, but enums cant contain floats, so this fixes that potential issue.
struct Data
{
	int health{};
	int maxHealth{};
	int attackPower{};
	int maxAttackPower{};
};


int main()
{
	Data data;

	Character Knight("Knight", health::start::Knight, health::max::Knight, data.attackPower = 50, data.maxAttackPower = 50);
	//Character Samurai("Samurai", data.health = 50, data.maxHealth = 70, data.attackPower = 300, data.maxAttackPower = 300);
	//Character Marine("Marine", data.health = 200, data.maxHealth = 250, data.attackPower = 100, data.maxAttackPower = 120);

	vector<Character> charList;

	charList.push_back(Knight);
	//charList.push_back(Samurai);
	//charList.push_back(Marine);

	for (int i = 0; i < charList.size(); i++)
	{
		cout << charList[i] << endl;
	}


	//Debug
	cout << "--DEBUG--\n" << endl;

	//Samurai.RestoreHealth(36);
	//Samurai.DisplayCharacterInfo(Samurai);

	Knight.RestoreHealth(49);
	Knight.DisplayCharacterInfo(Knight);

	cout << "--DEBUG--" << endl;
	//End Debug

	return 0;
}
I'll look over your code, I never use templates, probably should learn them. I did some editing and this is what I came up with, not sure if it's any better than what I had before though.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Item
{
public:
	Item();

	string GetItemName() const { return itemName; }

private:
	string itemName{};
	int cost{};
	int healthRestored{};
};

class Character
{
public:
	Character(string charClass, int charHealth, int charMaxHealth, int charAttackPwr, int charMaxAttackPwr) :
		charClass(charClass),
		charHealth(charHealth),
		charMaxHealth(charMaxHealth),
		charAttackPwr(charAttackPwr),
		charMaxAttackPwr(charMaxAttackPwr) {}

	string GetCharClass() { return charClass; }

	int GetCharHealth() const { return charHealth; }
	int GetCharAttackPwr() const { return charAttackPwr; }
	int GetCharMaxAttackPwr() const { return charMaxAttackPwr; }
	int GetCharMaxHealth() const { return charMaxHealth; }

	void TakeDamage(const int& damageTaken);
	void RestoreHealth(const int& restoreAmount);
	void UpgradeAttackPower(const int& upgradeAmount);
	void DisplayCharacterInfo(Character& character);

private:
	string charClass{};
	int charHealth{};
	int charMaxHealth{};
	int charAttackPwr{};
	int charMaxAttackPwr{};
};


ostream& operator<< (ostream& os, Character& character)
{
	os << "Class Name: " << character.GetCharClass() << endl;
	os << "Health: " << character.GetCharHealth() << endl;
	os << "Max Health: " << character.GetCharMaxHealth() << endl;
	os << "Attack Power: " << character.GetCharAttackPwr() << endl;
	os << "Max Attack Power: " << character.GetCharMaxAttackPwr() << endl;

	return os;
}

void Character::RestoreHealth(const int& restoreAmount)
{
	if (charHealth + restoreAmount <= charMaxHealth)
	{
		charHealth += restoreAmount;
	}
	if (charHealth + restoreAmount >= charMaxHealth)
	{
		charHealth = charMaxHealth;
	}
}

void Character::TakeDamage(const int& damageTaken)
{
	if (charHealth > 0)
	{
		charHealth -= damageTaken;

		if (charHealth <= 0)
		{
			charHealth = 0;
			cout << "The " << GetCharClass() << ", was defeated." << endl;
		}
	}
}

void Character::DisplayCharacterInfo(Character& character)
{
	cout << character << endl;
}


//Create a struct to give values a name instead of just a confusing number. 
//Could have used an enum, but enums cant contain floats, so this fixes that potential issue.
struct Data
{
	int health{};
	int maxHealth{};
	int attackPower{};
	int maxAttackPower{};
};


int main()
{
	Data data;

	Character Knight("Knight", data.health = 100, data.maxHealth = 150, data.attackPower = 5, data.maxAttackPower = 5);
	Character Samurai("Samurai", data.health = 50, data.maxHealth = 100, data.attackPower = 7, data.maxAttackPower = 7);
	Character Marine("Marine", data.health = 200, data.maxHealth = 250, data.attackPower = 4, data.maxAttackPower = 4);

	//Debug
	cout << "--BEGIN DEBUG--\n" << endl;

	Samurai.TakeDamage(Knight.GetCharAttackPwr());
	Samurai.DisplayCharacterInfo(Samurai);

	Knight.RestoreHealth(1);
	Knight.DisplayCharacterInfo(Knight);

	cout << "--END DEBUG--" << endl;
	//End Debug

	return 0;
}
Topic archived. No new replies allowed.