If I give a user a choice between 3 objects, how can I use the one he chose for the rest of the program?

At the beginning of my program asks a user if he wants monster A, B, or C (all from the same class). How do I then use that object for the remainder of the program?

Can I overload the >> operator and say something like:

1
2
3
Monster user; // monster to use the rest of the program;

cin >> user; 


and then use 'user' the rest of the time?
Polymorphism:
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
#include <iostream>
#include <string>

class Monster{
public:
	Monster(void) { name = "I am a monster who ";}
	~Monster(void) {}
	
	std::string name;
	
	virtual void speak(void) { }
};
class Walker  : public Monster{
public:
	Walker(void) { action = "walks"; }
	~Walker(void) {}
	
	std::string action;
	void speak(void) { std::cout << name << action << std::endl; }
};
class Looker  : public Monster{
public:
	Looker(void) { action = "looks"; }
	~Looker(void) {}
	
	std::string action;
	void speak(void) { std::cout << name << action << std::endl; }
	
};
class Thinker : public Monster{
public:
	Thinker(void) { action = "thinks"; }
	~Thinker(void) {}
	
	std::string action;
	void speak(void) { std::cout << name << action << std::endl; }
};



int main(void){	
	Monster* me = NULL;	
	char choice;
	
	do 
	{
		std::cout << "Type w, l, or t: ";
		std::cin >> choice;
		std::cin.ignore(90, '\n');
		switch(choice)
		{
		case 'w':
			me = new Walker;
			break;
		case 'l':
			me = new Looker;
			break;
		case 't': 
			me = new Thinker;
			break;
		}
	}
	while (choice != 'w' && choice != 'l' && choice != 't');
	
	me->speak();	
	
	delete me;
	return 0;
}

Last edited on
This is exactly what I was looking for! Thank you! I have a quick question: why did you use the * for Monster* me? What is the advantage of doing that rather than just making it a normal object?

Is it necessary because you are using 'new' to allocate space for Walker.Looker.Thinker, but not actually making them?
Last edited on
The asterisks (*) indicates that you're using a pointer (http://www.cplusplus.com/doc/tutorial/pointers/). If you're not familiar with the concept of pointers, be prepared to have your minded dazzled and numbed, then once you start using them you'll see they're actually very very useful and easy at that (Every single programmer I've talked to that knows pointers has said this: Pointers become extremely easy to work with once you wrap your head around the concept).

In this situation, he's allocating space for each object (And constructing it!), and simply storing the address in memory of that object in the pointer 'me'. 'me' then 'points' to an object of type 'Monster' and can be used to access it by using the -> operator (as opposed to the simple dot . operator).

The benefit of doing this instead of creating a 'regular' object is that the lifetime of 'me' is no longer related to the scope it is in. The object will exist in memory until you explicitly delete it by using the operator delete. This is beneficial because now you can pass the pointer around to functions or other variables while still referring to the same object.

If all of this sounds mind bogglingly difficult to grasp to you, don't fret because eventually everything will become clear. In my own experience, at some point during your programming journey you'll find yourself in need for exactly that which pointers offer, and you'll be somewhat forced to start using them. Once you get used to it though, you'll never look back and be glad you understand them :)
Last edited on
I used a pointer because I had to. The benefit is that I know there will be a monster, but I'm not sure what it will be until the user makes that choice. If that is beyond you, perhaps consider another method:
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
class Monster
{
public:
  Monster(int type);
  ~Monster(void) {}

  std::string name;

  void speak(void) { std::cout << "Hello, my name is " << name << std::endl; }
};

Monster::Monster(int type)
{
  switch (type)
  {
  case 0: name = "John";   break;
  case 1: name = "Frank";  break;
  case 2: name = "Henry"; break;
  default: name = "Non-Name";
  }
}

int main(void)
{
  int choice;
  do
  {
  cout << "Type 1, 2, or 3: ";
  cin >> choice;
  cin.ignore(69, '\n');
  }
  while (choice != 1 && choice != 2 && choice != 3);

  Monster me(choice);
  me.speak();
  
  return 0;
}


Maybe this is easier to understand. The downside is that for every function that is name dependent you need to check to see what the name is. This is not true for my first example.

There is no difference in scope between the two "me"s in my examples. The storage is allocated globally in the first example, but you still need to maintain the scope of me in order to know where that memory actually is.

Topic archived. No new replies allowed.