Was given an object oriented programming question in C++. I've gotta admit that i'm not the best when it comes to programming. I've attempted the question and found myself stuck. Here's the question:
FlyPigeonFly is a game rather like Simon says. It is played on a character-based console by very young children who are just learning to read.
It is an excellent exercise in quick verbal decision making and vocabulary building as well as reading skills.
FlyPigeonFly prints a motion verb ( fly, run, swim, crawl, walk, or roll ), waits for a second, then
prints the name of an entity and repeats the verb (for example: fly ..1s.. pigeon fly!.. ).
The player has ½ second to type y for yes or n for no. (case insensitive)
- If the answer is correct, the player scores, if incorrect, or if there was no answer within the ½ second, the player looses a point. When correct, all the motions the entity can perform are printed.
- When wrong, Ka..BOOM! is printed instead.
The default number of questions per player is 20, but the number can be changed by passing a different
number on the command line when starting the program.
For example: > FlyPigeonFly 10 will ask only 10 questions per player.
At the end of the run the players score (and the score of previous players if there were any) is printed, the
question: Another player (Y/N): is asked. The game exits if n is typed.
A typical output is reproduced below:
Player 1 starting.
You must answer with the letter y for YES, or n for NO.
Press [Enter] when ready to start:
1 fly pigeon fly!.. y
- I walk - I fly
2 swim Wheelbarrow swim.. n
- I roll
3 crawl ball crawl!..
Ka...BOOM!
4 fly plane fly!.. y
- I roll - I fly.
5 run boat run!.. n
- I roll.
6 walk engine walk!..
Ka..BOOM!
7 roll stone roll!.. y
- I roll.
. . .
16- crawl time crawl!.. y
- I crawl - I fly.
17- swim goose swim!.. n
Ka..BOOM!
18- run lizard run!.. y
- I run - I crawl.
19- run nose run.. y
- I run
20- fly goose fly!.. y
- fly - I walk I run I swim.
Player 1 *** score: 16 ***
Well done! Start another player (Y or N)? y
Player 2 starting
You must answer with the letter y for YES, or n for NO.
Press [Enter] when ready to start:
1 crawl giraffe crawl!.. y
Ka..BOOM!
2 roll river roll!.. n
- I run
3 swim crocodile swim!.. y
- I crawl - I walk - I run - I swim
. . .
Design Requirements:
To achieve a simple, easily maintainable object-oriented implementation, FlyPigeonFly uses inheritance, polymorphism and the STL. The minimum class requirement is given here:
* Each individual motion, ( fly, run, swim, crawl, walk, or roll ) is a singleton instance of a concrete class ( FlyMotion, RunMotion, SwimMotion, CrawlMotion, WalkMotion, RollMotion ) that
inherits from the Motion abstract class.
* Motion is a pure abstract class (also called an interface) with no data and the signature of two abstract function members:
// return a C-style string representing the concrete motion
virtual char * toString() const = 0;
// return true if key is found within the motion actors
virtual bool contains(const char * key) const = 0;
Motion has a stream insertion operator that prints - I then calls the toString() abstract- member function.
* The 6 concrete motion instances each contain a set of actors (C-style strings, const char *) that can perform the motion. These classes implement the Motion interface. Their toString() implementation prints the verb corresponding to the concrete motion and a trailing space, for example: roll , or swim . They must implement the singleton design pattern, so only one instance of a concrete motion can exist at one time
* A main (driver) controls the overall program logic and the interaction with the user. It maintains and activates a collection of 6 Motion pointers (which may, if you wish your program to be as OO as possible, be within another class).
The lists of actors that perform each concrete motion may be either read from file or hard-coded within the driver as you prefer.
-------------------------------------------------------------------------------------------------------------------
The attached code is what i've done so far. I've tried building it in CodeBlock and i've got these errors:
error: cannot allocate an object of type `Motion'
error: because the following virtual functions are abstract:
error: virtual bool Motion::contains(const char*) const
error: virtual char* Motion::toString() const
The first and second error refer to this portion of the code: Located in Motion.cxx
single = new Motion();
----------------------------------------------------------
The third and forth errors refer to these respectively: Located in Motion.h
public:
virtual char * toString() const = 0;
virtual bool contains(const char * key) const = 0;
I'm lost. Can anyone help me out? I have less then 3 days left to complete this task.
Thanks a lot in advance. :)
//Motion.h
#ifndef MOTION_H
#define MOTION_H
#include <iostream>
#include <string>
using namespace std;
class Motion
{
friend ostream &operator << (ostream &out, const Motion &m);
private:
static bool instanceFlag;
static Motion *single;
public:
// return a C-style string representing the concrete motion
virtual char * toString() const = 0;
// return true if key is found within the motion actors
virtual bool contains(const char * key) const = 0;
static Motion* getInstance();
inline virtual ~Motion()
{
instanceFlag = false;
}
};
#endif
//-----------------------------------------------------------
//Motion.cxx
#include <iostream>
#include <sstream>
#include <string>
#include "Motion.h"
ostream &operator << (ostream &out, const Motion &m)
{
out << "- I " << m.toString();
return out;
}
bool Motion::instanceFlag = false;
Motion* Motion::single = NULL;
Motion* Motion::getInstance()
{
if(! instanceFlag)
{
single = new Motion();
instanceFlag = true;
return single;
}
else
{
return single;
}
}
//-----------------------------------------------------------
//FlyMotion.h
#ifndef FLYMOTION_H
#define FLYMOTION_H
#include <iostream>
#include <string>
#include <set>
using namespace std;
#include "Motion.h"
class FlyMotion : public Motion
{
public:
static FlyMotion* instance();
virtual char * toString() const;
virtual bool contains(const char * key) const;
//~FlyMotion(){};
private:
static FlyMotion *inst;
set <string> actors;
set<char>::iterator act;
FlyMotion();
//FlyMotion(const FlyMotion&);
};
#endif
//-----------------------------------------------------------
//FlyMotion.cxx
#include <iostream>
#include <sstream>
#include <string>
#include "FlyMotion.h"
using namespace std;
FlyMotion* FlyMotion::inst = 0;
FlyMotion::FlyMotion()
{
inst = 0;
actors.insert("pigeon");
actors.insert("plane");
actors.insert("time");
actors.insert("goose");
}
FlyMotion* FlyMotion::instance()
{
if(inst == 0)
{
inst = new FlyMotion;
}
return inst;
}
char* FlyMotion::toString() const
{
ostringstream outStr;
outStr << Motion::toString() << "fly " << flush;
return outStr.str();
}
bool FlyMotion::contains(const char *key) const
{
act=actors.find(key);
return act!=actors.end();
}
//-----------------------------------------------------------
//mainDRV.cxx
#include <iostream>
#include <set>
#include "Motion.h"
#include "FlyMotion.h"
#include "RunMotion.h"
#include "SwimMotion.h"
#include "CrawlMotion.h"
#include "WalkMotion.h"
#include "RollMotion.h"
//const int size = 6;
int main()
{
FlyMotion *test1;
test1 = FlyMotion::getInstance();
if(test1->contains("pigeon"))
{
cout << "Test" << endl;
}
cout << "Press Enter to continue..." << flush;
cin.get();
return 0;
}
//-----------------------------------------------------------
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:
Select allOpen in new window
by: ZoppoPosted on 2009-11-03 at 08:52:35ID: 25730924
Hi IanCool,
the problem simply is that it's not possible to instantiate an object for an abstract class (a class which has at least one undeclared virtual function).
Therefor it's not possible to implement the 'Motion::getInstance' as you did.
IMO you have to implement a '...:getInstance' for each Motion-derived class because it has to know for which class it has to instantiate an object or i.e. implement 'Motion::getInstance' as a template method in a way it instantiates the derived class needed.
BTW: IMO you don't need the flag 'instanceFlag' since you can simply check if the instance is NULL ...
ZOPPO