friend help

I have to make CritterFarm a friend of Critter.

I'm trying to make all the critters talk. So I'm trying to get the class critter talk function to work first before I try the other functions.

I get : talk is not a member of critterfarm

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  //Critter Caretaker
//Simulates caring for a virtual pet

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std;

class Critter;

class CritterFarm
{
public:
	CritterFarm();
	~CritterFarm();
        Critter critters[5];
private:

};

//class definition -- defines a new type, Critter
class Critter
{
public:
	Critter(int hunger = 0, int boredom = 0);
	void Talk(CritterFarm & crt);                    //displays mood
	void Eat(int food = 5);         //reduces hunger level
	void Play(int fun = 5);         //reduces boredom level
	void PerformTrick();            //performs a random trick, if happy
	friend CritterFarm;

private:
	enum Mood { HAPPY, OKAY = 5, FRUSTRATED = 10, MAD = 15 };    //mood levels

	static const int NUM_TRICKS = 3;         //number of tricks
	static const string TRICKS[NUM_TRICKS];  //tricks

	int m_Hunger;                            //hunger level
	int m_Boredom;                           //boredom level

	string GetMood() const;                  //returns mood
	void PassTime(int time = 1);             //increases hunger, boredom levels
};

//tricks
const string Critter::TRICKS[NUM_TRICKS] = { "roll over",
"jump",
"do a backflip" };

CritterFarm::CritterFarm()
{
}

CritterFarm::CritterFarm()
{
}

//constructor
Critter::Critter(int hunger, int boredom) :
	m_Hunger(hunger),
	m_Boredom(boredom)
{}

//returns mood
string Critter::GetMood() const
{
	string mood;

	if (m_Hunger + m_Boredom > MAD)
		mood = "mad";
	else if (m_Hunger + m_Boredom > FRUSTRATED)
		mood = "frustrated";
	else if (m_Hunger + m_Boredom > OKAY)
		mood = "okay";
	else
		mood = "happy";

	return mood;
}

//increases hunger and boredom levels
void Critter::PassTime(int time)
{
	m_Hunger += time;
	m_Boredom += time;
}

//displays mood
void Critter::Talk(CritterFarm & crt)
{
	cout << "I'm a critter and I feel " << GetMood() << "." << endl;
	this->PassTime();
}

//reduces hunger level
void Critter::Eat(int food)
{
	cout << "Brruppp." << endl;
	m_Hunger -= food;
	if (m_Hunger < 0)
	{
		m_Hunger = 0;
	}
	PassTime();
}

//reduces boredom level
void Critter::Play(int fun)
{
	cout << "Wheee!" << endl;
	m_Boredom -= fun;
	if (m_Boredom < 0)
	{
		m_Boredom = 0;
	}
	PassTime();
}

//perform a random trick, if happy
void Critter::PerformTrick()
{
	//if not happy, no trick
	if (GetMood() != "happy")
	{
		cout << "I don't feel like doing a trick." << endl;
	}
	//perform a trick
	else
	{
		int choice = (rand() % NUM_TRICKS);       //random index number
		string trick = TRICKS[choice];            //trick to perform
		cout << "I " << trick << "." << endl;
	}

	PassTime();
}

int main()
{
	srand(static_cast<unsigned int>(time(0)));

	CritterFarm crit;

	int choice;
	do
	{
		cout << endl << "Critter Caretaker" << endl;
		cout << "-----------------" << endl << endl;
		cout << "0 - Quit" << endl;
		cout << "1 - Listen to your critter" << endl;
		cout << "2 - Feed your critter" << endl;
		cout << "3 - Play with your critter" << endl;
		cout << "4 - Ask your critter to perform a trick." << endl << endl;

		cout << "Choice: ";
		cin >> choice;

		switch (choice)
		{
		case 0:
			cout << "Good-bye." << endl;
			break;
		case 1:
			crit.Talk();
			break;
		case 2:
			crit.Eat();
			break;
		case 3:
			crit.Play();
			break;
		case 4:
			crit.PerformTrick();
			break;
		default:
			cout << endl << "Sorry, but " << choice;
			cout << " isn't a valid choice." << endl;
		}
	} while (choice != 0);

	return 0;
}
Last edited on
closed account (E0p9LyTq)
http://www.cplusplus.com/doc/tutorial/inheritance/
I think there is no need to friendship between Critter and CritterFarm since they are not related.
I see it as "Has-A" relationship -> Aggregation
https://www.infoworld.com/article/3029325/application-development/exploring-association-aggregation-and-composition-in-oop.html

I would create a vector of Critters in your CritterFarm.
Friends mean trouble. Prefer composition. Thomas1965 is right about relationship.


Just to verify that, which of these describes your situation best:

* The Farm has the liberty to rape all Critters, free and domestic.

* The Farm is a Critter.

* The Farm has Critters.
* The Farm has the liberty to rape all Critters, free and domestic.

lel. Friends don't let friends get raped ;D
Can we please not toss around the word "rape" in such a lightweight fashion? It's in disgracefully poor taste.
This is the project:

Write a program, Critter Farm, that manages a group of Critters. You can use the Critter class defined in the Critter Caretaker game program from Chapter 6 to represent individual critters on the farm; however each critter should now start with random hunger and boredom levels from 0 to 10. Implement the farm by writing a CritterFarm class with a data member that is an array of five objects.

Your program should instantiate a CritterFarm object and allow a player to manipulate through a menu with the following choices:
Choice 1 should make all the Critters talk.
Choice 2 should make all the Critters eat.
Choice 3 should make all the Critters play.
Choice 4 should ask all the Critters to perform a trick.

There should also be a secret menu choice of -1. If the player enters the choice, the CritterFarm's object should display each critter object's hunger and boredom private data member values. Accomplish this by making CritterFarm a friend of Critter.


This is the original example:
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
//Critter Caretaker
//Simulates caring for a virtual pet

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std;

//class definition -- defines a new type, Critter
class Critter
{
public:          
    Critter(int hunger = 0, int boredom = 0); 
    void Talk();                    //displays mood
    void Eat(int food = 5);         //reduces hunger level
    void Play(int fun = 5);         //reduces boredom level
    void PerformTrick();            //performs a random trick, if happy

private:
    enum Mood {HAPPY, OKAY = 5, FRUSTRATED = 10, MAD = 15};    //mood levels
    
    static const int NUM_TRICKS = 3;         //number of tricks
    static const string TRICKS[NUM_TRICKS];  //tricks
    
    int m_Hunger;                            //hunger level
    int m_Boredom;                           //boredom level

    string GetMood() const;                  //returns mood
    void PassTime(int time = 1);             //increases hunger, boredom levels
};

//tricks
const string Critter::TRICKS[NUM_TRICKS] = { "roll over", 
                                             "jump", 
                                             "do a backflip" };  
                                             
//constructor
Critter::Critter(int hunger, int boredom):
    m_Hunger(hunger),
    m_Boredom(boredom)
{}

//returns mood
string Critter::GetMood() const 
{
    string mood;

    if (m_Hunger + m_Boredom > MAD)
        mood = "mad";
    else if (m_Hunger + m_Boredom > FRUSTRATED)
        mood = "frustrated";
    else if (m_Hunger + m_Boredom > OKAY)
        mood = "okay";
    else
        mood = "happy";
        
    return mood;
}

//increases hunger and boredom levels
void Critter::PassTime(int time)
{
    m_Hunger += time;
    m_Boredom += time;
}

//displays mood
void Critter::Talk()
{
    cout << "I'm a critter and I feel " << GetMood() << "." << endl;
    PassTime();
}

//reduces hunger level
void Critter::Eat(int food) 
{
    cout << "Brruppp." << endl;
    m_Hunger -= food;
    if (m_Hunger < 0)
	{
        m_Hunger = 0;
	}
    PassTime();
}

//reduces boredom level
void Critter::Play(int fun)
{
    cout << "Wheee!" << endl;
    m_Boredom -= fun;
    if (m_Boredom < 0)
	{
        m_Boredom = 0;
	}
    PassTime();
}

//perform a random trick, if happy
void Critter::PerformTrick()
{
    //if not happy, no trick
    if (GetMood() != "happy")
    {
        cout << "I don't feel like doing a trick." << endl;
    }
    //perform a trick
    else
    {    
    	int choice = (rand() % NUM_TRICKS);       //random index number
        string trick = TRICKS[choice];            //trick to perform
        cout << "I " << trick << "." << endl;
    }
    
    PassTime();
}
    
int main()
{
    srand(static_cast<unsigned int>(time(0)));  
    
    Critter crit;

    int choice;  
    do 
    {
        cout << endl << "Critter Caretaker" << endl;
        cout << "-----------------" << endl << endl;
        cout << "0 - Quit" << endl;
        cout << "1 - Listen to your critter" << endl;
        cout << "2 - Feed your critter" << endl;
        cout << "3 - Play with your critter" << endl;
        cout << "4 - Ask your critter to perform a trick." << endl << endl;   

        cout << "Choice: ";
        cin >> choice;

        switch (choice)
        {
        case 0:	
            cout << "Good-bye." << endl;
			break;
        case 1:	
            crit.Talk();
			break;
        case 2:	
            crit.Eat();
			break;
        case 3:	
            crit.Play();
			break;
        case 4:	                                              
            crit.PerformTrick();
			break;
        default:
            cout << endl << "Sorry, but " << choice;
			cout << " isn't a valid choice." << endl;
        }
    } while (choice != 0);

    return 0;
}
Last edited on
There is no real need for friendship.

It is quite easy to create a Farm that has five Critters. Everything that the Farm has to do to the Critters requires only the public interface of the Critters. (Only the initialization to random levels requires a little trickery.)

I don't need to be a friend to do this:
1
2
3
4
5
6
7
8
9
Critter farm[5]; // these have hunger=0, bored=0

farm[0] = Critter( 4, 7 ); // replace first critter
farm[2] = Critter( 10, 10 ); // replace third critter

// farm Play
for (auto & c : farm) {
  c.Play(2);
}



Edit: Teacher wan't friends. The Farm depends on Critters, for it has them. The Critters have to declare a friend. Circular dependency?

No. http://en.cppreference.com/w/cpp/language/friend
1
2
3
4
5
6
7
8
9
10
class CritterFarm; // forward declaration

class Critter {
  friend CritterFarm;
  // normal code
};

class CritterFarm {
  // normal code
}
Last edited on
Thanks. Here is updated code(I think its finished):

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

//Critter Caretaker
//Simulates caring for a virtual pet

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>

using namespace std;

class CritterFarm;

//class definition -- defines a new type, Critter
class Critter
{
public:
	Critter(int hunger = (rand() % 11), int boredom = rand() % 11);
	void Talk();                    //displays mood
	void Eat(int food = 5);         //reduces hunger level
	void Play(int fun = 5);         //reduces boredom level
	void PerformTrick();            //performs a random trick, if happy
	friend CritterFarm;

private:
	enum Mood { HAPPY, OKAY = 5, FRUSTRATED = 10, MAD = 15 };    //mood levels

	static const int NUM_TRICKS = 3;         //number of tricks
	static const string TRICKS[NUM_TRICKS];  //tricks

	int m_Hunger;                            //hunger level
	int m_Boredom;                           //boredom level

	string GetMood() const;                  //returns mood
	void PassTime(int time = 1);             //increases hunger, boredom levels
};


class CritterFarm
{
public:
	CritterFarm();
	~CritterFarm();
	Critter critters[5];
	void Display();
private:

};


//tricks
const string Critter::TRICKS[NUM_TRICKS] = { "roll over",
"jump",
"do a backflip" };

CritterFarm::CritterFarm()
{
}

CritterFarm::~CritterFarm()
{
}

//constructor
Critter::Critter(int hunger, int boredom) :
	m_Hunger(hunger),
	m_Boredom(boredom)
{}

//returns mood
string Critter::GetMood() const
{
	string mood;

	if (m_Hunger + m_Boredom > MAD)
		mood = "mad";
	else if (m_Hunger + m_Boredom > FRUSTRATED)
		mood = "frustrated";
	else if (m_Hunger + m_Boredom > OKAY)
		mood = "okay";
	else
		mood = "happy";

	return mood;
}

//increases hunger and boredom levels
void Critter::PassTime(int time)
{
	m_Hunger += time;
	m_Boredom += time;
}

//displays mood
void Critter::Talk()
{
	cout << "I'm a critter and I feel " << GetMood() << "." << endl;
	PassTime();
}

//reduces hunger level
void Critter::Eat(int food)
{
	cout << "Brruppp." << endl;
	m_Hunger -= food;
	if (m_Hunger < 0)
	{
		m_Hunger = 0;
	}
	PassTime();
}

//reduces boredom level
void Critter::Play(int fun)
{
	cout << "Wheee!" << endl;
	m_Boredom -= fun;
	if (m_Boredom < 0)
	{
		m_Boredom = 0;
	}
	PassTime();
}

//perform a random trick, if happy
void Critter::PerformTrick()
{
	//if not happy, no trick
	if (GetMood() != "happy")
	{
		cout << "I don't feel like doing a trick." << endl;
	}
	//perform a trick
	else
	{
		int choice = (rand() % NUM_TRICKS);       //random index number
		string trick = TRICKS[choice];            //trick to perform
		cout << "I " << trick << "." << endl;
	}

	PassTime();
}

void CritterFarm::Display()
{
	for (int i = 0; i < 5; i++)
	{
		cout << "Hunger: " << critters[i].m_Hunger << endl;
		cout << "Boredom: " << critters[i].m_Boredom << endl;
	}
}

int main()
{
	srand(static_cast<unsigned int>(time(0)));

	CritterFarm crit;

	int choice;
	do
	{
		cout << endl << "Critter Caretaker" << endl;
		cout << "-----------------" << endl << endl;
		cout << "0 - Quit" << endl;
		cout << "1 - Listen to your critter" << endl;
		cout << "2 - Feed your critter" << endl;
		cout << "3 - Play with your critter" << endl;
		cout << "4 - Ask your critter to perform a trick." << endl << endl;

		cout << "Choice: ";
		cin >> choice;

		switch (choice)
		{
		case -1:
			crit.Display();
			break;
		case 0:
			cout << "Good-bye." << endl;
			break;
		case 1:
			for (int i = 0; i < 5; i++)
			{
				crit.critters[i].Talk();
			}
			break;
		case 2:
			for (int i = 0; i < 5; i++)
			{
				crit.critters[i].Eat();
			}
			break;
		case 3:
			for (int i = 0; i < 5; i++)
			{
				crit.critters[i].Play();
			}
			break;
		case 4:
			for (int i = 0; i < 5; i++)
			{
				crit.critters[i].PerformTrick();
			}
			break;
		default:
			cout << endl << "Sorry, but " << choice;
			cout << " isn't a valid choice." << endl;
		}
	} while (choice != 0);

	return 0;
}
Yep, this works. You have to be really trusting of CritterFarm to be a good friend! As a friend, CritterFarm could actually modify the private data of each Critter as well, so in general you want to shy away from this design. But if it's a requirement... oh well.

To see Critter hunger and boredom levels, typically you'd add useful public getter methods to your Critter, e.g. int GetBoredom() , int GetHunger(), which would simply return [value copies of] the private member objects.

Edit: there is one little thing I noticed which you could improve ;D CritterFarm has a certain number of Critter s, which you arbitrarily set to 5. This is fine, but main() doesn't know this. How did main() know to iterate only up to 5?
What I'm getting at is to move all the loops in your main() switch statement over to CritterFarm methods. Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class CritterFarm
{
public:
    CritterFarm();
    ~CritterFarm();
    
    void Display();

    // Makes all critters in the farm talk
    void Talk()
    {
        for (int i = 0; i < 5; i++)
            critters_[i].Talk();
    }

private:
    Critter critters_[5];

};


Last edited on
... and to follow up on icy1's suggestion - that allows you to define a constant in one place for the number of critters, so that you don't use magic numbers throughout your code.
Topic archived. No new replies allowed.