Selection Structures - Birth of a Bird

main1.png main2.png main3.png

In almost every instance in which we want to solve a problem, we select between different options depending on whether certain conditions are met. Computer programs are built to solve problems, therefore they should have a structure that allows them to make decisions and select alternatives. In C++, selections are structured using if, else, else if or switch. Relational expressions and logical operators are common when handling selection structures. In this laboratory experience, you will practice the use of some of these selection structures by completing a design using the class called Bird. In addition, you will review concepts related to objects.

Objectives:

  1. Use relational expressions and select adequate logical operators to make decisions.
  2. Apply selection structures.
  3. Analyze the declaration of a class to understand how to create and manipulate objects of the class.
  4. Practice the creation and manipulation of objects, and the invocation of its "setters" and "getters".

Pre-Lab:

Before you get to the laboratory you should have:

  1. Reviewed the following concepts related to decision structures:

    a. Logical operators

    b. if, else, else if.

  2. Reviewed the following concepts related to objects and classes in C++:

    a. the creation of objects of a class.

    b. using the "getter" methods to access an object's attributes.

    c. using the "setter" methods to modify an object's attributes.

  3. Studied the documentation for the Bird class available in this link.

  4. Studied the concepts and instructions for this laboratory session.

  5. Taken the Pre-Lab quiz, available in Moodle.



To facilitate this laboratory experience, we will begin by reviewing some concepts related to objects and we will describe the Bird class.

Classes and Objects in C++

An object is an entity that contains data and procedures to manipulate them. Similar to how each variable has a type of data associated to it, each object has a class associated to it, which describes the properties of the objects: its data (attributes), and the procedures that can be used to manipulate its data (methods).

It is not necessary to know all of the details about the methods of the object to define and use an object, but you must know how to create it and how to interact with it. The necessary information is available in the class' documentation. Before creating objects of any class, we should familiarize ourselves with its documentation. The documentation indicates, among other things, what entity is trying to be represented in the class, and its interface or methods available to manipulate the objects of the class.

Take a look at the documentation of the Bird class which can be found in this link..

Classes

A class is a description of the data and processes of an object. The class’ declaration establishes the attributes that each of the objects of the class will have, and the methods that it can invoke.

If it isn't specified otherwise, the attributes and methods defined in a class will be private. This means that the variables can only be accessed and changed by the methods of the class (constructors, setters, and getters, among others).

The following is the skeleton of the declaration of a class:


class ClassName {
  // Declarations

private:
  // Declaration of variables or attributes
  // and prototype member functions
  // that are private for this class

   type privateVar
   type nameOfPrivateMemFunc(type of the parameters);

public:
  // Declarations of attributes
  // and prototypes of method functions
  // that are public for the entire program

   type publicVar;
   type nameOfPublicMemFunc(type of the parameters);
};

You can see the declaration of the Bird class in the file bird.h included in this laboratory experience's program.

Objects

An object is an entity that contains data (same as a variable), called its attributes, and it also contains procedures, called method, that are used to manipulate them. The objects are "instances" of a class that are created in a similar manner as how variables are defined:

ClassName objectName;

By creating an object we have available the methods of the class that the object belongs to.

Methods of a Class

The methods of a class determine the actions that we can take on the objects of that class. The methods are similar to functions in the sense that they can receive parameters and return a result. An elementary way to know the methods of a class is reading the class declaration. For example, the following is a section of the declaration of the class Bird in the file bird.h.


class Bird : public QWidget {
.
.
.
    Bird(int , EyeBrowType , QString , QString, QWidget *parent = 0) ;

    int getSize() const;
    EyeBrowType getEyebrow() const ;
    QString  getFaceColor() const;
    QString  getEyeColor() const;
    Qt::GlobalColor getColor(QString) const;

    void setSize(int) ;
    void setEyebrow(EyeBrowType) ;
    void setFaceColor(QString) ;
    void setEyeColor(QString) ;
.
.
.
};

Once the object is created, its methods provide the only way to change its attributes, to obtain information about them, or do computations with them. This is why the set of methods is commonly called the interface. The methods are the interface between the object’s user and its content.

In general, in each class the prototypes of the methods are defined to construct the objects, and to search, manipulate and store the data. The following is a general format of a method prototype:

typeReturned methodName(type of the parameters);

Afterwards, we write the corresponding function to the method in the project's code, starting with a header that includes the name of the class that the function belongs to:

TypeReturned ClassName::MethodName(parameters)

We declare public methods within the class so that objects that are instances of a class have permission to access private variables (these are the setters and getters). It's preferred to use private variables and access them through the setters and getters, instead of declaring them public since the object that is associated to these variables would have control over the changes that are made.

To invoke a method we write the name of the object, followed by a period and then the name of the method:

objectName.methodName(arguments);

Constructors

The first methods of a class that we should understand are the constructors. A class can have multiple constructors. One of the constructors will be invoked automatically each time an object of that class is created. In most cases, the constructors are used to initialize the values for the object’s attributes. To create objects of a class, we must know which are the constructors of the class.

In C++, the constructors have the same name as the class. The type returned by these functions is not declared since they do not return any value. Their declaration (included in the definition of the class) is like this:

methodName(type of the parameters);

The function header will be like this:

ClassName::MethodName(parameters)

The class Bird that you will be using in today's session has two constructors (overloaded functions):

Bird (QWidget *parent=0)

Bird (int, EyeBrowType, QString, QString, QWidget *parent=0)

You can see the declarations of the method prototypes in the declaration of the Bird class in the project's bird.h file. The documentation can be found in this link. The first constructor, Bird (QWidget *parent=0), is a method that can be invoked with one or no argument. If no argument is used, the function's parameter has a value of 0.

A class' constructor that can be invoked without using an argument is the class' default constructor; that is, the constructor that is invoked when we create an object using an instruction like:

Bird pitirre;

You can see the implementations of the class Bird in the file bird.cpp. Note that the first constructor, Bird (QWidget *parent=0), will assign random values to each of the object's attributes. Later on there is a brief explanation for the randInt function.

Have a look at the documentation for the second constructor, Bird (int, EyeBrowType, QString, QString, QWidget *parent=0). This function requires four arguments and has a fifth argument that is optional since it has a default value. One way to use this constructor is creating an object like this:

Bird guaraguao(200, Bird::UPSET, "blue", "red");

Setters (mutators)

Classes provide methods to modify the values of the attributes of an object that has been created. These methods are called setters or mutators. Usually, we declare one setter for each attribute that the class has. The Bird class has the following setters:

  • void setSize (int)
  • void setEyebrow (EyeBrowType)
  • void setFaceColor (QString)
  • void setEyeColor (QString)

You can see the method's declarations in Figure 1 and in the Bird class declaration in bird.h, and the implementation of the some of the methods in bird.cpp. The code in the following example creates the object bobo of the Bird class and then changes its size to 333.

Bird bobo;
bobo.setSize(333);

Getters (accessors)

Classes also provide methods to access (get) the value of the attribute of an object. These methods are called getters or accessors. We usually declare one getter for each attribute a class has. The Bird class has the following getters:

  • int getSize ()
  • EyeBrowType getEyebrow ()
  • QString getFaceColor ()
  • QString getEyeColor ()

You can see the declarations of the methods in Figure 1 and in the Bird class declaration in bird.h, and the implementations of some of the methods in bird.cpp. The code in the following example creates the object piolin of the Bird class and prints its size:

Bird piolin;
cout << piolin.getSize();

Other Functions or Methods You will use in this Laboratory Experience

MainWindow: The file mainwindow.h contains the declaration of a class called MainWindow. The objects that are instances of this class will be able to use the overloaded methods

void MainWindow::addBird(int x, int y, Bird &b)

void MainWindow::addBird(Bird &b)

that will add to the screen a drawing of an object of the Bird class that is received as an argument. The code in the following example creates an object w of the MainWindow class, creates an object zumbador of the Bird class and adds it in the position (200,200) on the screen w using the first method.

MainWindow w;
Bird zumbador;
w.addBird(200,200,zumbador);

figure1.png

Figure 1. Window w with the image of the object zumbador in the position (200,200).


Important! It's not enough to just create the Bird objects so that these appear on the screen. It's necessary to use one of the addBird methods to make the drawing appear on the screen.

randInt: The Bird class includes the method

int Bird::randInt(int min, int max)

to generate random numbers in the range [min, max]. The method randInt depends on another function to generate random numbers that require a first element or seed to be evaluated. In this project, that first element is generated with the function call srand(time(NULL)) ;.



Which of the following would make the object son of the Bird class have the height of its father \(also an object of the Bird class\)? son.setSize\( father.setSize\(10\) \); son.getSize\( father.getSize\(10\) \); son.setSize\( father.getSize\(\) \); son.setSize\(\) = father.get\(10\); We should invoke the method setSize on the son using as argument the result of invoking getSize on the father. The answer is hijo.setSize\( padre.getSize\(\) \);.
If the object mom has ”red” eyes, what eye color will the object son have after the following code?
”white” ”blue” ”red” ”yellow” Since mama.getEyeColor\(\) returns ”red”, the conditional expression on line 5 will become true, so the color ”white” is assigned to the eyes of son. Observe that the conditional expression on line 8 is also true, but in this case in the structure of `if-else if`, the first case that becomes true is the one that determines what block of code will be executed. The else if and else blocks are never executed in this case, and so the program continues onto what's after line 12.

If the object mom has ”red” eyes, what eye color will the object son have after the following code?
”white” ”blue” ”red” ”yellow” Since mama.getEyeColor\(\) returns ”red”, the conditional expression on line 5 will become true, so the color ”white” is assigned to the eyes of son. Afterwards, the conditional expression on line 8 also becomes true, so the color ”blue” is assigned to son. The final color is ”blue”.

The current size of the Bird called son is 15. What size value will the follow instruction assign to son if the mother has size 10?
son.setSize\( mother.getSize\(\) < 10 ? son.getSize\(\) : son.getSize\(\) \* 2 \);
9 10 15 30 The conditional expression mother.getSize\(\) < 10 is false \(since 10 is not less than 10\), and so the result of the expression mother.getSize\(\) < 10 ? son.getSize\(\) : son.getSize\(\) \* 2 is 15 \* 2, or 30.



Laboratory session:

Exercise 1 - Study the Inheritance Rules for the Birds Family

The Birds Family

Juana and Abelardo, mother and father birds, are about to have a baby they will call Piolín. As with real birds, the "Qt birds" expect their babies to have inherited attributes from their mother and father.

When the laboratory experience is finished, your program will create two birds (Juana and Abelardo) with random characteristics and a third bird (Piolín), with characteristics determined by the parent's characteristics, following a set of rules similar to the rules of genetic inheritance.

Inheritance Rules

Eye Color

The baby will always inherit the mother's eye color

Size

The size of the bird is smallest between the mother's or father's size.

Face Color

The gene dominance for the face color is given by the following list, ordered from color with most dominance color to color with least dominance:

  1. blue
  2. green
  3. red
  4. white
  5. yellow

The baby will inherit the face color most dominant from the parent's colors. For example, a baby whose mother has a green face and whose father has a white face, will have a green face.

Eyebrows

The gene dominance for the eyebrows is given by the following list, ordered from eyebrows with most dominance to eyebrows with least dominance:

  1. Bird::ANGRY
  2. Bird::BUSHY
  3. Bird::UNI
  4. Bird::UPSET

The genes in the eyebrows follow these rules:

  • If both parents have "angry" eyebrows, the baby will have "unibrow" eyebrows.
  • If both parents have "unibrow" eyebrows, the baby will have "upset" eyebrows.
  • In other cases, the baby will inherit the eyebrows with most dominance from the parent's eyebrows.

Exercise 2 - Study the main Function

Instructions

  1. Load the project BirthOfABird into QtCreator. There are two ways to do this:

    • Using the virtual machine: Double click the file BirthOfABird.pro located in the folder /home/eip/labs/selections-birthofabird of your virtual machine.

    • Downloading the project’s folder from Bitbucket: Use a terminal and write the command git clone http:/bitbucket.org/eip-uprrp/selections-birthofabird to download the folder selections-birthofabird from Bitbucket. Double click the file BirthOfABird.pro located in the folder that you downloaded to your computer.

  1. Configure the project.

  2. Compile and run the project. You should see a window with two birds that represent Juana and Abelardo. After a second, you will witness the birth of their baby, Piolín. Despite that, this Piolín could have been from another nest and not their son since it has random characteristics.

  3. Open the file main.cpp (you will not make changes in any other file in this project). Study the main function. You will NOT make changes to the main function. Note that the main function essentially does two things:

    i. Creates three birds and adds two of them to the window.

    ii. Creates a timer that waits a second and after invokes the birth function passing by reference to the window and the three birds.


    funcionMain.png

    Figure 2. Main function.


Exercise 3 - Write the Code to determine Piolín's Characteristics

Study the header for the birth function. In this function, write the necessary code so baby Piolín has the characteristics dictated by the rules of inheritance exposed previously.


funcionBirth.png

Figure 3. Birth function



Deliverables

Use "Deliverable" in Moodle to upload the main.cpp file with the modifications you made to the birth function. Remember to use good programming techniques, include the names of the programmers involved, and document your program.



References

https://sites.google.com/a/wellesley.edu/wellesley-cs118-spring13/lectures-labs/lab-2

results matching ""

    No results matching ""