Вы находитесь на странице: 1из 35

G64OOS Lab Manual

Peer-Olaf Siebers Michel Valstar Tuesday 24th April, 2012

Chapter 1 Introduction
This lab manual is both the companion guide to the taught lab sessions of G64OOS Object Oriented Systems, as well as the detailed description of the assessed coursework. The taught lab sessions span 10 weeks, and are divided in three parts: an introduction to C++ (2 weeks), Analysis & Design (4 weeks), and Object Oriented Programming (4 weeks). The lab companion guide provides a short description of the topics addressed in each lab session, references to the relevant sections in the C++ in 24 hours and Stroustrup books, example code, extra exercises, and links to additional information on the Net. The assessed coursework section explains in great detail what you need to do for your coursework, and how the coursework will be graded. The coursework is split into two major parts, one on Analysis and Design, and the other on actual Object Oriented Programming. You will notice that rather than providing a single problem for you to solve, we have organised the coursework into smaller pieces. This allows us to focus on dierent sub-problems while maintaining an overall coherence to the coursework.

Chapter 2 Lab Companion Guide


The lab companion guide provides description of what well cover each week, together with example code and data. It does not cover everything that will be discussed during the actual lab sessions, and working through the companion guide is in no way a suitable substitute for attending the lab sessions. The questions and exercises often require you to go beyond the material discussed during the lectures, and sometimes beyond the associated chapters in the Stroustrup and 24hrs books. For these cases, remember: the Internet is your friend. A particularly good resource is www.cplusplus.com. The coursework for G64OOS is split in two parts: one on object-oriented analysis and design (OOA/OOD), and the second on object oriented programming (OOP). The OOA/OOD coursework is a group project resulting in a consultancy-style report. The OOP coursework is an individual project resulting in a working program, complete with source code.

2.1

Introduction to C++

Week 20 - Hello world, operators, functions, and a class


This weeks lab work is intended to get you started writing C++. To do so, we will use Code::Blocks, a cross-platform, free IDE. It is installed in the labs, but you can download it from http://www.codeblocks.org/. When installing it, you will have to select which compiler to use. If you are on Mac or Linux, g++ is your best choice. If you are using windows, you have many options. We recommend using MinGW. You can either install that separately, or get the Code::Blocks setup package with MinGW included. If that does not work for you, install the MinGW software separately. See the Code::Blocks installation page for more information. Hello world To get started, open Code::Blocks, and click on Create a New Project in the main pane. Select a Console Application, make it a C++ application, and give it an appropriate name. It is easiest to use the same project for 5

CHAPTER 2. LAB COMPANION GUIDE

all Introduction to C++ exercises, but if you insist you can create a new project for every exercise. If you browse the Sources folder in your project browser (left pane), you will nd a le names main.cpp. Open this in the main pane. It should have the following code:
Listing 2.1: Hello World++
1 2 3 4 5 6 7

#include <iostream> int main() { std::cout << "Hello world!" << std::endl; return 0; }

If not, create this le and copy this text into it. Notice the main() function in the le called main.cpp. This is the function that your machine calls rst upon running your program. Every program must have exactly one main function, and it must return an int. It can have input parameters, which are normally used to pass command line arguments to the program (see this excellent tutorial on the use of command line arguments for more information. Exercise w20.1: Extend the hello world example to ask for a users name. Provide a means for the user to input their name using std::cin. After the user gives their name, print the text Well hello, $user!, where $user is the name provided using std::cin. See chapter 4 of the 24hrs book, or search www.cplusplus.com for more information on std::cin. Operators Lets do some maths. Type in or copy the following code and execute the resulting program:
Listing 2.2: Operators
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

#include <iostream> using namespace std; /* Compute point on a line */ int main() { float b, c; float y,x; cout << "Give angle of line: "; cin >> b; cout << "Give offset of line: "; cin >> c; cout << "Give value of x: "; cin >> x; cout << "The corresponding value on the line " << b << "x+" << c << " is: ";

2.1. INTRODUCTION TO C++


19 20 21 22 23 24

y = b*x+c; cout << y << endl; return 0; }

You can do this in the same le as your hello world example, but that would mean you lose that precious work. Instead, you could add a new le to the project (FileNewEmpty le), in which you put the code above. This does cause a problem: you now have two les in your project that contain a main function, and as we said earlier, every program can have only one. The solution to this is to remove the hello world le from the project (right-click, remove le from project). Dont worry, removing it from the project does not mean the le is deleted. Note that in the hello world example we used std::cout to print output to the screen, while in listing 2.2 we left out the std:: part of the statements. We are able to do so because in line 3 we declare to use that namespace as a default. This often saves us a lot of work typing in the explicit namespaces that functions and classes originate from, but it generates the risk of ambiguity if the same class or function name is used in two dierent namespaces. In general, it is safe to use the standard library std namespace, but more care should be taken with third-party libraries. See the cplusplus tutorial on namespaces for more information. Exercise w20.2: extend the program to compute the y -value of a quadratic function ax2 + bx + c, given the value of x. Functions Using functions is usually your rst taste of the aspects of code re-use and encapsulation of functionality. Note that it does not allow for data encapsulation, however. Unless you make use of unsavory tricks, all data generated within a function is limited to the scope of that function. It is thus only a partial step towards full encapsulation. In the Operators exercise above, you had to compute the square of a number by doing something like:
1

int y = x*x;

If you would like to raise x to the power of 3, you would have to do something like:
1

int y = x*x*x;

The reason for this is that the C++ list of operators is limited to +, , , /, and %, for addition, subtraction, multiplication, division, and computing the remainder of a division. Note that there is no operator for raising powers. Yet writing powers the way we showed above is very tedious, and would change depending on the power to which we raise it. This is an ideal example of where using a function would be very helpful. Consider the following code:

8
Listing 2.3: Functions
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

CHAPTER 2. LAB COMPANION GUIDE

#include <iostream> using namespace std; float raisePower(float x, int a); int main() { float x, y, v, w; int a; cout << "Give value for x: "; cin >> x; cout << "Give value for y: "; cin >> y; cout << "Raise to the power of: "; cin >> a; v = raisePower(x, a); w = raisePower(y, a); cout << endl << x << " to the power of " << a << " is: " << v; cout << endl << y << " to the power of " << a << " is: " << w; cout << endl <<"(x+y) to the power of " << a << " is: " << raisePower(x+y, a); return 0; } float raisePower(float x, int a) { float v = x; for (int i=1; i<a; i++) v *= x; return v; }

In the code in listing 2.3, on line 5 we declare the prototype of our function raisePower, which takes a oating point base number x and raises it to the power of b, where b is an integer. The actual denition of the function is given after the main function, on lines 29-35. The declaration of raisePower has to appear in the code before its use in the main function. Yet for clarity, we choose to put the implementation details at the end of the listing. Later you will learn to do this in a more structured manner, where you keep separate les that contain all class and function prototypes. These les are called header les. Note the use of the mixed assignment/operator = in line 31. This multiplies the value of v by x and assigns the result to v . All operators can be combined with assignment in this way. Try to run this code. Question w20.1: What happens if you provide a negative value for the power? What if you provide 0? Look at the way v and i are initialised.

2.1. INTRODUCTION TO C++

Could you get the same or better results by initialising them dierently? Exercise w20.3: Fix the raisePower code so it can deal with negative powers, and 0. Exercise w20.4: Rewrite the quadratic equation solver so it has a function with prototype:
1

float quadratic(float a, float b, float c, float x);

The function should in turn use your new function raisePower. Classes We mentioned in the previous section that functions only partly cover encapsulation, because they do not store any data. Classes on the other hand can store data, and thus give you all the opportunity to deliver full encapsulation. Consider the following implementation of a class that generates quadratic equations:
Listing 2.4: Classes
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

#include <iostream> using namespace std; float raisePower(float x, int a); class Quadratic { private: float a, b, c; +c

// Defining the quadratix function ax2+bx

public: Quadratic(float x, float y, float z); void set_a(float x); void set_b(float x); void set_c(float x); float compute(float x) const; }; Quadratic::Quadratic(float x, float y, float z) { a = x; b = y; c = z; } void Quadratic::set_a(float x) {a = x;} void Quadratic::set_b(float x) {b = x;} void Quadratic::set_c(float x) {c = x;} float Quadratic::compute(float x) const { return a*raisePower(x,2) + b*x + c; }

10
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

CHAPTER 2. LAB COMPANION GUIDE


float raisePower(float x, int a) { float v = x; for (int i=1; i<a; i++) v *= x; return v; } int main() { Quadratic Q = Quadratic(1, 2, 3); float x = 0; cout << "Give value for x: "; cin >> x; float y = Q.compute(x); cout << "Corresponding value of quadratic function is: " << y << endl; }

By default, all members of a class are considered private, and thus not directly accessible by non-member functions. This means that the private: declaration on line 9 is redundant. We leave it there for clarity purposes only. Line 18 shows the use of the so-called const correctness best practice. It declares that the function compute(oat x) doesnt change any data within the class. Because compute is never intended to do so, the use of the const keyword will instruct the compiler to throw an error when we inadvertently do change data in our implementation of compute(oat). Thus, using const correctness diligently reduces the bugs in your software, and improves maintainability. Const correctness can get some time getting used to, and we suggest you read the two excellent tutorials on this: one on www.possibility.com, and the other in www.parashift.com. Exercise w20.5: Change the constructor to set a, b, and c on the rst line of the constructors denition instead of in its body (i.e. on line 21 in listing 2.4). Exercise w20.6: Make the setter functions set a, set b, and set c inline. Question w20.2: Why cant you make the function set a const? Question w20.3: Why would it not make sense to make raisePower a member function of the Quadratic class?

2.1. INTRODUCTION TO C++

11

Week 21 - Pointers, arrays, inheritance, and templates


This weeks lab is designed to help you understand two important aspects of C++: pointers and inheritance. A pointer is used to directly address and access a computers memory. As such it is an incredibly powerful tool, but because it works with the machine at such a low level, it can be complicated to use. Still, having pointers allows you to create fast and small programmes, and it is for this reason that it is still the industry standard in areas that require a lot of fast data manipulation, such as computer vision or machine learning. Inheritance is one of the cornerstones of the Object Oriented paradigm. It allows you to use abstraction by making generalisations about a certain class, and dening details in their sub-classes. Often the super-classes are called base-classes or the parents of a class. In turn, de inheriting classes are often called the children of a class. Pointers Ever wondered exactly where in memory a variable, object, or function was stored? In C++ you can know exactly that by using pointers. Pointers allow direct access to a memory location, and form an alternative way of addressing a variable.
Listing 2.5: Pointers
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

#include <iostream> using namespace std; int main() { int carSpeed = 10; int busSpeed = 8; int acc = 0; // -- Create a pointer object int *p1 = NULL; cout << "The value of pointer p1 is: " << p1 << endl; // -- Storing an objects address in a pointer p1 = &carSpeed; int *p2 = &busSpeed; cout cout cout cout << << << << "The speed of the car is " << *p1 << "this is stored at memory location " "The speed of the car is " << *p2 << "this is stored at memory location " " m/s, "; << p1 << endl; " m/s, "; << p2 << endl;

// -- Manipulating ojbects through pointers cout << endl << "Accelerate bus by how many m/s?: "; cin >> acc; *p2 += acc; cout << "New bus speed is " << *p2 << "m/s" << endl; }

12

CHAPTER 2. LAB COMPANION GUIDE

Consider listing 3.1. Notice what happened to the actual value of p1. The rst time this is printed (on line 12), the value is 0. The second time however, it has a very dierent value. The exact value depends on the state of your machine at the time of execution. Exercise w21.1: Check that p1 holds the same address as the variable carspeed by directly acessing carspeed s address using the address of operator &. Exercise w21.2: Check that busSpeed indeed holds the new value printed in line 28 by printing it directly instead of via pointer p2. Question w21.1: Why cant you tell beforehand what the values of p1 and p2 are, unless you set them to 0 or NULL? Question w21.2: What could happen if you do not initialise a pointer to 0?

Parameter Passing
One of the reasons why pointers exist is so you can pass arguments by reference instead of by value, the latter being the default way. Question w21.3: Look at Listing 2.6. What do you expect will be printed on standard output? Run the code of Listing 2.6. Chances are that the output is not at all what you expected, and even if you did expect this output, it probably isnt what the poor programmer who wrote this code intended to happen.
Listing 2.6: Parameter passing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

#include<iostream> using namespace std; void halve(float x); // - This function halves the value of x

int main() { float v = 64; for (int i=0; i<6; i++) { halve(v); cout << "v = " << v << endl; } } void halve(float x) { x = x/2; }

Exercise w21.3: Fix the code of Listing 2.6 to let function halve modify the value of x as intended. Do this by changing the function passing to take a pointer to a variable instead of the actual variable. Exercise w21.4: Like the previous exercise, but use references instead of pointers (hint: a reference to x would be &x. Question w21.4: Whats the dierence between a reference to a variable and a pointer to a variable? Question w21.5: The function using references looks much cleaner. Why would you ever want to use pointers?

2.1. INTRODUCTION TO C++ Arrays

13

Arrays are contiguous portions in memory, sequentially storing a number of elements the same type. The number of elements to store has to be known in advance (if you dont know this, you probably want to use Vectors). Consider listing 2.7.
Listing 2.7: Arrays
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include <iostream> #include <math> #define PI 3.14159265 using namespace std; int main() { const int n = 5; int odd[n]; for (int i=0; i<n; i++) { cout << odd[i] << endl; } cout << endl; int even[n] = {0, 2, 4, 6, 8}; for (int i=0; i<n; i++) { cout << even[i] << endl; } }

Question w21.6: Whats the dierence in output of the arrays odd and even? Question w21.7: What happens if you write a value in odd[5]? Question w21.8: How can you extend an array? Exercise w21.5: write a function that asks for 7 inputs, and prints all odd numbers, and returns all input numbers that were odd in a new array. Exercise w21.6: Write a function that takes an array as input, and returns the sum of all the values Exercise w21.7: Combine the code of the previous two exercises to create a new function that asks for 7 inputs, prints all odd numbers, their sum, and returns the array of odd numbers. Bonus: modify this function so that instead of always requesting 7 inputs, it rst asks how many numbers to input.

14

CHAPTER 2. LAB COMPANION GUIDE

2.2

Analysis and Modelling

Week 22 - Use Cases, Class-, Sequence-, and State machine-diagrams


This lab is split into two parts. In the rst hour, you will nish the tea example we started in the Lecture within work groups. In the second hour, you should start with the Object Oriented Analysis and Modelling (OOAM) Coursework. During this lab, we advise you to use the Visual Paradigm UML Drawing Software, which is installed on the lab machines. A community edition is available from http://www.visual-paradigm.com/. An alternative software suite for UML drawing would be Astah Community Edition. Hour 1: All diagrams for preparing a cup of tea Usecase (chart using <<include>> + <<extend>> where appropriate, base path, alternative path). Question w22.1 : How could you deal with the fact that people do things in a dierent order (e.g. milk before sugar or sugar before milk) or use dierent quantities (e.g. 1 or 2 spoons of sugar)? Class diagram (attributes, operations, including association and multiplicity indicators) Question w22.2 : Do we really need the class Person? Sequence diagram(s) State machine diagram(s) Question w22.3 : What are the main dierences between activity and state machine diagrams? If you have spare time choose additional diagram types (see http: //www.uml-diagrams.org/uml-24-diagrams.html) Present and discuss solutions (our job!) Hour 2: Start with Coursework Clarify that we will only explain the case; we will not help you to solve it; assume we are the clients; we can only help you with the requirement analysis; in the next lab we will answer some high level technical questions; however, as the submission date is shortly after the lab we would propose not to leave everything until the last minute Question w22.4 : Which of the following would you use as classes and why would you use them (remember that the tips given during the lecture are only rules of thumb - you still have to use your common sense; you might want to review the answer to this question at a later stage)?

2.2. ANALYSIS AND MODELLING

15

Possible classes: sensors, plants, greenhouses, weather (relevant?), temperature (outside/inside) (class?), light (class?), lighting system, heating system, farmer (relevant?), energy control system, water (class?), water supply system, feeding system

16

CHAPTER 2. LAB COMPANION GUIDE

Week 23
Task 1: Modelling how to make a cup of tea (hour 1) Here is the activity diagram from the last lecture of how to make a cup of tea Create additional UML diagrams to describe the process further! Task 2: Modelling the eBay buying/selling process (hour 1) If you have never used eBay have a look here to nd out how it works http://pages.ebay.co.uk/help/account/getting-started.html Here is a basic UseCase diagram to get you started

2.3. OBJECT ORIENTED PROGRAMMING

17

2.3

Object Oriented Programming

Week 24
Inheritance A good example of inheritance is the idea of shapes. A rectangle is a shape, and so is a circle. A square could be dened as a special type of rectangle, where the width is always equal to the height of the rectangle. Such shapes would probably share similar variables, such as their centre of mass, and you would probably dene similar operations on them, such as area() or circumference(), but the way they would be implemented would be completely dierent. Fig. 2.1 gives an example class diagram for this family of objects, and listing 2.8 gives an example implementation of the base class Shape and the derived class Rectangle.

Figure 2.1: Class diagram for Shape class and derived classes.

Listing 2.8: Shape


1 2 3 4 5 6 7 8 9 10 11 12 13 14

#include <iostream> using namespace std; /* Class definitions */ class Shape { protected: int centre[2]; public: // -- Constructor with Centre given, c must be a 2-element array Shape(int c[]);

18
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

CHAPTER 2. LAB COMPANION GUIDE


void move(int d[]); virtual float area() = 0; virtual float circumference() = 0; }; class Rectangle: public Shape { int height; int width; public: // -- Constructor with Centre and side given Rectangle(int c[], int h, int w); }; /* Main function */ int main() { } /* Class implementations */ Shape::Shape(int c[]) { centre[0] = c[0]; centre[1] = c[1]; } void Shape::move(int d[]) { centre[0] += d[0]; centre[1] += d[1]; } // -- Rectangle constructor Rectangle::Rectangle(int c[], int h, int w): Shape(c), height(h ), width(w) {}

Exercise w24.1: Implement the classes Circle :public Shape and Square :public Rectangle. Exercise w24.2: Try to create an object of class Shape in the main function. Can you? Think of implementing the functions area() and cirumference(). How would you do that? Does all this make sense to you? If it doesnt, turn Shape into an abstract base class by turning one or more of its member functions into pure virtual function. Question w24.1: Do you need to make both area() and circumference() pure virtual to make Shape an abstract base class? Does it make any difference whether you make both pure virtual? Exercise w24.3: Implement the overriding of the (pure) virtual functions area() and circumference() for the classes Rectangle, Square, and Circle. Exercise w24.4: Implement the function max x(), that returns the maximum x-value of the space occupied by a shape. For example, in case of a 4 by 4 square, centred at position [x,y] = [1,1], max x would return the value 3. Think carefully in what class(es) this should be dened, and how.

2.3. OBJECT ORIENTED PROGRAMMING Object containers

19

It is possible to mix objects of dierent classes in a container such as an array, as long as they have the same base class. An example of this is given in Listing 2.9.
Listing 2.9: Arrays of shapes
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include <iostream> int main() { // -- Create some locations int L0[2] = {0, 0}; int L1[2] = {1, 1}; int L2[2] = {3, 5}; // -- Create some shape objects Rectangle *R1 = new Rectangle(L0, 2, 4); Rectangle *R2 = new Rectangle(L1, 4, 2); Circle *C = new Circle(L2, 1); // -- Group the shape objects in an array Shape* S[3] = {R1, C, R2}; // -- Mamma always told... delete R1; delete R2; delete C; }

Exercise w24.5: Write a (set of) function(s) that ask(s) for user input to create a number of shapes. It should rst ask how many shapes the user wants to create, and then for each shape what type of shape, followed by asking the user to input the variables relevant to that shape type. You should return an array of Shape pointers. Hint 1: Look at slide 21 of Lecture 5 for inspiration. Hint 2: You may want to store the length of the array somewhere. How to do that? One way is to split the user input operation in two functions, rst asking for the number of shapes, then the details of each shape. The second way would be to use pointers, but that is more complicated. Exercise w24.6: Write the function void moveShapes(Shape* S, int* d) that takes an array of shapes of dierent types and moves each by the same displacement d. Check that this works by printing the locations of the centres of all shapes in S . Exercise w24.7: Write the function oat mixedShapesArea(Shape* S that takes an array of shapes of dierent types and returns the sum of their individual areas. Exercise w24.8 Write the function void sortShapesByArea(Shape* S, int n) that sorts the elements in an array S of length n by area, with the smallest area rst. Exercise 24.9 Write the function void lineUpShapes(Shape* S, int n) that lines up all shapes left-to-right, with the y-value of the centre of each

20

CHAPTER 2. LAB COMPANION GUIDE

shape having the same value, and the minimum x-value of each next shape being one greater than the maximum x-value of the previous shape. See Fig. 2.2 for an example of this (the gure also contains Triangles, which you dont need to implement). You will have to implement the member function Shape::min x() to do this.

Figure 2.2: Number of 2-Dimensional geodesic shapes on a line. Optional exercise: As an optional extra exercise, you can write void print() functions for all classes. Then try to generate a number of shapes using the interface created in exercise w24.5, and sort them by area, line them up, and print them to your screen. To make things easier, you may wish to restrict this to printing squares and rectangles (printing circles is much harder).

2.3. OBJECT ORIENTED PROGRAMMING

21

Week 25

This weeks lab will let you perform operations on sets of related objects. The general principle is to access the concrete objects through an interface dened by an Abstract Base Class (ABC). You will be practising good coding practices as well. Write all class and function denitions in a header le, all class and function implementations in a .cpp le, and write the main function of the program you create in a separate le called main.cpp. You should also comment your code, and use const correctness. You will be writing a component of a robots AI, that deals with sets of 3-Dimensional wooden blocks. There are three types of blocks: cubes, cylinders, and cones. The blocks come in four colours: red, green, yellow, and blue. The robot is to perform tasks on a set of blocks such as sorting them, or picking the brightest coloured block. Listing 2.10 gives a rst version of the abstract base class Shape3D. Create a new le called Shape3D.h and copy the code from listing 2.10 into it.
Listing 2.10: Shape3D
1 2 3 4 5 6 7 8 9 10 11 12 13

#include <iostream> using namespace std; enum BlockColour{RED, GREEN, YELLOW, BLUE}; class Shape3D { protected: BlockColour colour; public: Shape3D(BlockColour c); // - Constructor with only a colour specified

22
14 15 16 17 18

CHAPTER 2. LAB COMPANION GUIDE

string getColour() const; void setColour(BlockColour c); virtual float volume() const = 0; };

Exercise w25.1: Extend Shape3D.h to include denitions for the Cube, Cylinder, and Cone classes. Think about what the minimum set of variables is that each class needs. Next, create a new le called Shape3D.cpp. This is where you will implement the Shape3D family of classes. Exercise w25.2: Implement the constructors and methods for Shape3D, Cube, Cylinder, and Cone. Exercise w25.3: Extend Shape3D to include the function void print() const;. The function should output the type of an object, the colour, and the volume. Decide whether you should implement that as a single function of Shape3D, or as a polymorph function. Exercise w25.4: Write a (set of) function(s) that ask(s) for user input to create a number of shapes. It should ask for each shape what type of shape, its colour, followed by asking the user to input the variables relevant to that shape type. You should return either a vector or a list of Shape3D pointers. Look at slide 21 of Lecture 5 for inspiration. Adapt the code to suit your denition, if needed, and edit the main.cpp le you have to let the user create a set of blocks. Use either the vector or list container to store the blocks. Exercise w25.5: : Add a void printBlockSet(vector<Shape3D*>) or void printBlockSet(list<Shape3D*>) function to the Shape3D.h. This function prints a set of blocks. Before printing each block, it states what position in the container it occupies. Implement the function in Shape3D.cpp and modify the main.cpp le to print the set of blocks provided by the user. We now want the robot to be able to sort the blocks in various ways. In particular, we want the robot to sort blocks by volume and by colour. Exercise w25.6: Write a function that sorts either a list of Shape3D pointers or a vector of Shape3D pointers by volume. Edit the main.cpp to print the Shape3D objects sorted by volume after a user provides details of the shapes. Exercise w25.7: Write a function that sorts either a list of Shape3D pointers or a vector of Shape3D pointers by the brightness of the colour. As a denition, we declare that yellow is the brightest colour, followed by red, then green, and nally blue. Edit the main.cpp to print the Shape3D objects sorted by colour after you have printed the list sorted by volume.

2.3. OBJECT ORIENTED PROGRAMMING

23

Week 26 - Test Driven Development Setting up UnitTest++ for your projects in Code::Blocks
I use the LeapYear project from Lecture 7 as an example here Download the compiled version of UnitTest++ from the module website (or get the original source les from http://unittest-cpp.sourceforge.net/). My compiled version comes in a folder [TestPit]. Create a new project LeapYear.cbp. The project should be stored within the [TestPit] folder and needs to contain the following les: main.cpp LeapYear.h LeapYear.cpp LeapYearTest.cpp

Goto menu [Project/Build options] and add a link library from the UnitTest++ folder via a relative path (..\UnitTest++\Deliv\Release\libUnitTest++.a).

Goto menu [Project/Build options] and add a search directory path for the compiler (..\UnitTest++\src).

Replace the code in main.cpp with the code in Listing 2.11 (this basically runs all the unit tests we create).
Listing 2.11: Leap year test main
1

#include "UnitTest++.h"

24
2 3 4 5

CHAPTER 2. LAB COMPANION GUIDE

int main() { return UnitTest::RunAllTests(); }

Test your setup by building and running your project. If everything goes well, you should be getting the output shown in Fig. 2.3.

Figure 2.3: Correct output for the Unit++ base code. If you get the same output as shown in Fig. 2.3 you can start adding tests and code. Remember: Your tests should all be located in your LeapYearTest.cpp, your class denition(s) in LeapYear.h and your class implementation in LeapYear.cpp; main.cpp should be used as a high-level controller. Read through the UnitTest++ documentation (in particular the Getting started and Simple check macros section) Have a look at the examples in TestUnitTest++.cpp (TestPit/UnitTest++/src/tests/) to see how to use the dierent types of macros. Tasks for Lab 7 Exercise w26.1 : Team up with a buddy and redo the LeapYear example from Lecture 7 in XP style (and without looking at the lecture slides). The task is to create a function that checks if a given year is a leap year or not Logic: A year is a leap year when it can be divided by 4, unless it can be divided by 100. But in case it can be divided by 400, then again it is a leap year. Tip: We used the CHECK EQUAL tests in the lecture Exercise w26.2 : Read through the Money tutorial. Although this tutorial is written for Visual Studio the strategies described are not specic to any particular IDE. Try to implement the source code step-by-step yourself. If you get stuck have a look at the module website where you nd the Code::Blocks version of the code. Exercise w26.3 : Use a TDD approach to dene a bank account class. The class should have the following functionality: Crediting and debiting the account Displaying the current balance Simple menu for choosing service requirements Create account

2.3. OBJECT ORIENTED PROGRAMMING

25

Exercise w26.4 : Work by yourself now! Try the TDD approach with one of the coursework classes of previous weeks (e.g. the Shape or Shape3D classes).

Chapter 3 Object Oriented Programming Coursework

3.1

Synopsis

It is the year 2317, and Earth is too crowded. To date, space travel has been limited to our own solar system, but a recent invention allows entire space eets to be transported with near-light speed velocity. A number of Earths biggest corporations have decided to grasp this opportunity and colonise the closest known habitable planet, Gaia, which is a mere 33 light-years away from earth. A race is gathering pace. To keep competition fair, the United Nations have specied a date on which all corporations will launch their eets together, and have set up rules to determine who will eventually own Gaia. 27

CHAPTER 3. OBJECT ORIENTED PROGRAMMING 28 COURSEWORK The design of such a eet is complex: corporations have access to a variety of spaceships, each with dierent characteristics. At the core of the eet, there are the colonisation ships (CS), that carry colonists. Then there are the solar sail ships (SSS) which provide power converted from starlight to the eet, medical ships that prevent disease, and military ships to protect from alien attacks. Thanks to the recently invented faster-than-light (FTL) bubble ship, individual ships dont need their own FTL drive. Theres a catch though: the heavier the eet, the slower the bubble moves. The technology behind the FTL-bubble ship is kept secret by the United Nations Space Agency (UNSA), and UNSA is providing each corporation with a single FTL-bubble ship. Under UN law - now universally accepted - war is illegal. To resolve rival corporations laying claim on the same planet, they have to abide to a simple set of rules: if a planet is uninhabited (i.e. the corporation is the rst to arrive), the corporation is free to colonise it. If it is not empty, the arriving corporation can colonise it only if it arrives with more colonists than are living on the planet upon arrival. When this happens, the current inhabitants pack their bags and use the ships of the rival corp that just claimed their planet to start searching for another place to live. No colonists of the arriving corp are lost in this process. So, the more people in your eet, the greater the chance you win the planet Gaia! Theres a catch though: due to space limitations, a eets population cant grow in transit. On the other hand, a population on a planet grows by 5% year on year.

3.2

Coursework

It is your task to implement a space eet that adheres by the rules specied in sections 3.1 and 3.3, implementing ships with specications provided in section 3.4, and an interface to the game simulator specied in section 3.5. You are largely free to implement this however you like, as long as you adhere to the rules specied in this coursework. A few constraints do apply: the program has to be written in isostandard C++. You can only use standard library (STL) classes besides the classes you dene yourself. The sourcecode should compile on our machine, that is, it should compile on mersey using gcc. To be very specic, the command gcc Fleet.h -o Fleet.o should work on mersey. You have to hand in the coursework in a zip le, containing your name and student number. See section 3.6 for details about the deliverables.

3.3

Game Rules

Below are the rules to which the game, and thus your code, must and will adhere: Money Each corporation (thats you, the student!) has the same xed amount of money to spend on ships, to wit, 10,000.- UNP (United

3.3. GAME RULES

29

Nations Pounds). The price of ships is xed and provided in section 3.4. Energy Ships require energy. All ships in your eet must have power, or else the entire eet wont move. Military Military escort ships protect colony ships. How many colony ships each escort ship can protect depends on its size, and is listed in 3.4. It is your choice to protect your ships or not. Military escort ships protect bigger colony ships before protecting smaller ships. Space Attack Exactly halfway during the space voyage, the eet is attacked by aliens. A random 25% of colony ships (rounded up) not protected by a military escort is destroyed, and the remains are left behind by the eet. Disease Shortly after the attack by aliens, a disease breaks out on one of the remaining colony ships (randomly chosen). If the eet does not have a medic ship, all colonists on that ship die. The ship will continue to travel with the eet though. Colonisation As stated in the synopsis, what happens when a eet arrives at Gaia is governed by two rules: if you are the rst to arrive, your colonists settle on the planet and your colonisation population starts to grow (see below for details). If you arrive and the planet is already inhabited, two things can happen: either your eet is carrying more colonists than the current planet population, and you take over, settling down with all your colonists, or if you arrive with fewer colonists in your eet than there are people on the planet, you lose. Planet population growth Every year, the population of the planet grows by 5%. This happens instantly, after exactly one year has passed. Distance to planet The planet is 33 light years away from Earth. Fleet speed The speed of the FTL-Bubble is determined as follows: c v= w (3.1)

where v is the eet speed in meters per second, c is the speed of light, and w is the eet weight, i.e. the sum of the weights of all ships in your eet. is set to 10 for this coursework. Winner The corporation (student) populating Gaia in the end has won.

30

CHAPTER 3. OBJECT ORIENTED PROGRAMMING COURSEWORK

3.4

The Ships

From the synopsis and rules sections, you probably gather that there are quite a few ships involved in this game. You will have to implement them all. Below is a list of all ships, per category. It also lists for every ship what the values are for their respective attributes. Note that you dont have to implement the Bubble Ship.

Colony Ships
There are three dierent colonisation ships, each with dierent costs, weight, and energy consumption. The properties of each ship is listed in table 3.1. Name Ferry Liner Cloud Colonists 100 250 750 Cost 500 1000 2000 Weight 10 20 30 Energy Consumption 5 7 9

Table 3.1: Colony ship attributes.

Solar Sail Ships


There are two types of Solar Sail Ships, the standard ship Radiant, and the massive Ebulient. The Ebulient is so big, that it can often provide energy for an entire eet. See table 3.2 for details. Name Radiant Ebulient Energy Generation 50 500 Cost 50 250 Weight 3 50 Energy Consumption 5 5

Table 3.2: Solar Sail Ship attributes.

Military Escort Ships


There are three dierent Military Escort Ship types: the light and fast Cruiser, the medium-sized Frigate, and the great alien thumper Destroyer. The ships have been designed to be fast and light, but are pretty expensive and consume a lot of power. Each ship will protect a number of colony ships (other ships wont get attacked). The second column in table 3.3 tells you how many, and the rest of the table provides all remaining information you need to implement these ships.

Medic Ship
There is only one type of Medical ship, called the Medic. It is very small and ecient, but rather expensive. The benet of this ship type is that if

3.5. INTERFACE WITH GAME ENVIRONMENT Name Cruiser Frigate Destroyer Escorted ships 3 5 7 Cost 500 1000 2000 Weight 5 7 9 Energy Consumption 10 20 30

31

Table 3.3: Military Escort Ship ship attributes.

you choose to include one in your eet, it will render your eet immune to disease. Details of the ship are provided in table 3.4. Name Medic Cost 1000 Weight 1 Energy Consumption 1

Table 3.4: Medical Ship attributes.

3.5

Interface with Game Environment

You must implement the following elements of the interface with the simulation program:
Listing 3.1: Interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

int Fleet::getWeight() const; // Returns cumulative weight of fleet int Fleet::getEnergyConsumption() const; // Returns cumulative energy consumption of fleet int Fleet::getColonistCount() const; // Returns cumulative colonist count of fleet int Fleet::getCost() const; // Returns cumulative fleet cost int Fleet::EnergyProduction() const; // Returns cumulative energy production of fleet int Fleet::countProtectedShips() const; // Returns nr of colony ships protected in fleet bool Fleet::hasMedic() const; // Returns True if the fleet has a medic ship, false otherwise string Fleet::getCorporationName() const; // Returns your chosen name of your corporation. Ship* Fleet::getShipByNumber(int i) const;// Returns pointer to the i-th Ship in the fleet vector<int> Fleet::protectedShips() const;// Returns a vector with ship numbers of protected colony ships vector<int> Fleet::unprotectedShips() const; // Returns a vector with ship numbers of unprotected colony ships vector<int> Fleet::colonyShips() const; // Returns a vector with ship numbers of all ships that are a colony ship vector<Ship*> Fleet::shipList() const; // Returns a vector with all ships in the fleet void Fleet::destroyShip(int i); // Removes ship i from the fleet int Ship::getEnergyConsumption() const; // Returns energy consumption of a ship

32
16 17 18

CHAPTER 3. OBJECT ORIENTED PROGRAMMING COURSEWORK


int Ship::getWeight() const; // Returns weight of a ship int Ship::getCost() const; // Returns cost of a ship string Ship::getTypeName() const; // Returns the ship type, e.g. Ferry, Cruiser, or Ebulient. Note that spelling mistakes may effect your grade! bool Ship::isDestroyed() const; // Returns true if the ship is destroyed, false otherwise int ColonyShip::getColonistCount() const; // Returns nr of colonists of a ship void ColonyShip::infect(); // Infects a colony ship bool ColonyShip::isInfected() const; // Returns True if the ship is infected with a disease, False otherwise int SolarSailShip::getEnergyProduction const; // Returns energy production of Solar Sail Ship int MilitaryEscortShip::getNrProtected() const; // Returns nr of colony ships protected by this ship

19 20 21 22 23 24

3.6

Deliverables

You need to hand in the following four les: 1. Fleet.h, containing the denition of your classes and functions. 2. Fleet.cpp, containing the implementation of your classes and functions. 3. $studentid$ eet.dat, your eet data le containing the eet you want to enter in the competition. 4. $studentid$ report.pdf, which is your report containing class diagram, class diagram description, and class specication. Where $studentid$ is your student number. The format of the eet data le should be as follows: Each line contains the information of the number of ships of each type, by putting the ship type name rst, followed by whitespace, followed by the number of ships of that type. Note that if you dont have any ships of a particular type, you may simply omit it from your eet data le. See Listing 3.2 for an example of a small eet. N.B. DO NOT include the line numbering of the listing in your eet data le!.
Listing 3.2: Fleet Data Example
1 2 3 4

Ferry 3 Cruiser 1 Medic 1 Radiant 1

The report should contain an image of the class diagram and the relationships between classes of your program. Make sure it includes all elements of the interface code you need to implement! With the class diagram should come a description of the diagram, in text. For each class in your class

3.6. DELIVERABLES

33

diagram, you will have to ll in a table just like that shown in Table 3.5. Note that, dierent to CRC-cards, we want you to use the actual function names and use the full signatures of the functions and variables (including const-ness). Class name: Base class: Derived class: Component of: Component classes: Function: Variables

Description

Operations

Description

Table 3.5: Class specication template

Note that the Base class/Derived class elds should hold only the rst generation up or down a class family tree. The Component of eld should list classes that use this class as a component (usually as a member variable). The eld Component classes on the other hand lists classes that are added as components or aggregates to this class. The Function: eld should give a very short description of the function of this class (i.e. the reason for its existence). Variables and operations should have the same name as your variables and operations in the class diagram and in your C++ implementation, but you dont have to mention return types or whether they are public, private, or protected. In case you plan to write your report in LaTeX (always a laudable idea), the code for this table is provided in listing 3.3.
Listing 3.3: LaTeX table code
1 2 3 4 5 6 7 8 9 10 11 12 13

\begin{table}[h] \begin{center} \begin{tabularx}{1.0\textwidth}{|X|X|} \hline \multicolumn{2}{|X|}{Class name:} \\ \multicolumn{2}{|X|}{Base class:} \\ \multicolumn{2}{|X|}{Derived class:} \\ \multicolumn{2}{|X|}{Component of:} \\ \multicolumn{2}{|X|}{Component classes:} \\ \hline \multicolumn{2}{|X|}{Function:} \\ \hline \hline

34
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

CHAPTER 3. OBJECT ORIENTED PROGRAMMING COURSEWORK


Variables & Description \\ \hline & \\ & \\ & \\ \hline Operations & Description \\ \hline & \\ & \\ & \\ \hline \end{tabularx} \label{t:classSpecification} \end{center} \end{table}

Besides the interface with the game environment, your code should implement the following functionality: A user interface that lets a user compose a eet, and returns a pointer to that eet. Call the function Fleet* userInterfaceCreateFleet() ;. The user interface should be interactive, and use the keyboard and screen only. Implement eet persistence by creating a function that takes a (pointer to a) Fleet object and saves it to a eet data le, as well as a function that takes a lename to a eet data le and returns a (pointer to a) Fleet object. The format of the eet data le is described above.

Submission Guidelines
The deadline for course work submission is the 03/05/2012, 16:00. Late delivery of the coursework will result in a penalty of 5% per day. To reference other works please use the Harvard style. Please submit all your les archived in a single zip le named $studentid$.zip where $studentid$ represents your student number.

Electronic Submission
You will need to ensure that your $studentid$.zip le is located on your Unix leserver (which will be robin, tuck, much, scarlet or marian). One way to do this is to log into a lab machine and copy $studentid$.zip onto your H: drive. Log into your home Unix machine. Change to the directory containing the $studentid$.zip le you wish to submit. Type: cw submit $studentid$.zip Select the ID for the coursework you are submitting. Enter y to conrm. A receipt number will be displayed and you will receive an emailed receipt also. Should you wish to change your submission before the deadline, you can resubmit using the same steps. Resubmissions will replace your original submission. Resubmitting after the deadline will result in a penalty for missing the deadline (see above) even if your original submission

3.7. MARKING

35

was before the deadline. If you have any trouble with this operation please contact one of the module convenors (well before the deadline!).

Plagiarism
No marks will be awarded for regurgitation of lecture notes or material from text books, or copying the code of your fellow students. You must complete this piece of work independently as an individual. Copying other students work will incur severe penalties. Each submitted le will be automatically checked against every other le submitted.

3.7

Marking

The coursework will be marked on a number of things: correct use of Object Oriented Paradigms (e.g. encapsulation, inheritance, composition), nontechnical quality of your code (e.g. symmetry, le organisation, whitespace, and comments), as well as technical quality of your code (e.g. eciency of search/optimisation code, minimisation of data/functionality redundancy). Below is a breakdown of exactly how marks will be assigned: 1. Documentation 20% Class diagram (INCLUDING RELATIONSHIPS) 10% Class specication (using the template provided in Table 3.5) 5% Description of Class diagram 5% 2. Implementation 60% Compilation 15% Adheres to Ship/Fleet specication 5% Adheres to Interface specication 10% Coding good practice 10% Consistency with class diagram 10% Code elegance 10% 3. Oral exam 20% Your code and eet data le will be checked for correctness (e.g. that you didnt overspend on the eet, or that all ships have power). If your eet is not launch ready, you will not get full points for the Ship/Fleet specication. The oral exam will last 10 minutes and will be held during the last lab, on Monday 14 May 2012. You are requested to be available during the full 2 hour period of the lab. During the oral exam, we will ask you specic questions about elements of your code. The winner of the space race will be immortalised on the courses website.

Вам также может понравиться