Constructors and Member Functions

Setup

Follow the GitLab instructions to create a new project for lab03 and clone it into your ~/si221/labs/directory.

Introduction

This lab is designed to provide you some practice with using and creating modules centered around classes that make use of private/public data access, constructors for initialization, and member functions.

Part 1 (20 points): Use a class with constructors, member functions, and private data

Consider the class Point shown below. The Point class was discussed in the last section of the lecture on Constructors & Destructors. We're going to work with points again, and focus on the following:

  1. the use of private data that the user of class Point can't get at,
  2. the use of member functions, and
  3. the use of constructors.

Create Point.h and Point.ccp files using the following code:

Point.h Point.cpp
/***************************************************
* Defines a class Point for manipulating points in
* the plane.  The user is kept away from the
* implementation using the public/ private mechanism.
* The user can create points (and initialize them),
* read data from an input stream to set point coordinates
* and, query the coordinates of points.
***************************************************/
#ifndef _POINT_
#define _POINT_
#include <iostream>
using namespace std;

class Point{
private:
  double x, y, z;

public:
  // constructor sets to (a,b,c) or defaults to (0,0,0)
  Point(double  a = 0.0,  double  b = 0.0,  double c = 0.0);

  double get_x() const;      // return x-coordinate
  double get_y() const;      // return y-coordinate
  double get_z() const;      // return z-coordinate
  void readIn(istream &IN);    // read point from IN in
                             // ordered triple format:
                             // (a.b,c.d,e.f)
};

Point midpoint(const Point &P, const Point &Q);
#endif
#include "Point.h"

Point::Point(double a, double b, double c){
  x = a;
  y = b;
  z = c;
}

double Point::get_x() const {
  return x;
}

double Point::get_y() const {
  return y;
}

double Point::get_z() const {
  return z;
}

void Point::readIn(istream &IN){
  char c;
  IN >> c >> x >> c >> y >> c >> z >> c;
}

Point midpoint(const Point &P, const Point &Q){
  return Point((P.get_x() + Q.get_x())/2,
         (P.get_y() + Q.get_y())/2,
         (P.get_z() + Q.get_z())/2);
}

For the first part of this lab you get to practice being a user of a class with member functions, constructors, and private data. You're going to use Point.h and Point.cpp to write a program that reads two points from standard input and prints out the midpoint of the two points. You may not modify the code of Point.h and Point.cpp in any way.

You must create a file named part1.cpp containing the code below to form your solution. Note: That's "add to", not "change"!

part1.cpp

/******************************
 * template code for part1.cpp
******************************/
#include "Point.h"
#include <iostream>
using namespace std;

int main(){
  // Declare points and prompt user for input


  // Read in the points using the member function


  // Print the points using member "getter" functions


  // Compute & print the midpoint


  return 0;
}

When your program runs, it should look exactly like the samples below.

Waiting for user input After user inputs points

Part2 (30 points): Write your own member functions for classes (and stand alone functions)!

The class Point defined above is really just a start. There's a lot more functionality that you could add. Some would most appropriately be member functions, others stand alone functions. In this part of the lab, you are going to modify Point.h and Point.cpp to add two things:

  1. a member function writeOut to match the existing member function readIn. Since we are asking for an operation on one particular point, it makes sense to define this as a member function - writeOut will belong to the point object you're printing. Hint: you should make use of an ostream argument so that a call like midpoint(A,B).writeOut(cout) would work.
  2. a stand alone function dist taking two points and returning the distance between them. It makes sense to define dist as a stand-alone function as neither point is naturally distinguished as the one to which such a function would belong. Try to use const as appropriate!

If you've made the above changes properly, you should be able to rewrite the driver program from Part 1 as part2.cpp using the following template:

part2.cpp

#include "Point.h"
#include <iostream>
using namespace std;

int main(){
  // Declare points and prompt user for input


  // Read in the points using the member function


  // NEW: Print the points using the writeOut function


  // NEW: Compute the midpoint and print using the writeOut function


  // NEW: Compute & print distance between the points


  return 0;
}

When your program runs, it should look exactly like the samples below.

Waiting for user input After user inputs points

Part 3 (10 points): Intermission/Commentary

Remember, we're all about separating interface from implementation, so that the user doesn't have to concern himself with how something works, just what it does. Consider Point.h and Point.cpp; if we wanted to change our implementation so that it kept points in cylindrical form (i.e. a radius, an angle and a height instead of x, y and z coordinates), nothing would change from the user's perspective. You might rename the private data members x, y and z to something like r, a and h, but he can't use those variables in his program anyway, since they're private. Of course some of the definitions in Point.cpp would change, but the user never needs to see those anyway.

Keeping everything we just said above in mind, what's the difference between defining member functions within the class and placing the definition in the associated .cpp file? Place your answer in a file named part3.txt. Hint: refer back to Lab01 and consider what files were (and weren't) provided to you.

Part4 (40 points): Defining a class

Now it's your turn to create a class from scratch. I tell you what I need in this class; you provide the definition! You will define a class Date, for representing dates. A user of your class should be able to:

  1. initialize the month, day and year of a Date object,
  2. ask if one date comes before another,
  3. increment the date by a day, and
  4. read a date from standard input.

The below function definitions are provided for you to use in your implementation:

// Takes a year y (e.g. 1998) and returns true
// if it's a leap year and false otherwise
bool leapyear(int y){
  return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}

// Takes a year y and month m (e.g. 2002 and 12) and
// returns the number of days in month m given that
// it falls in year y.  (The year matters because of
// February and leap years!)
int daysinmonth(int y, int m){
  if (m == 9 || m == 4 || m == 6 || m == 11)
    return 30;
  else if (m != 2)
    return 31;
  else
    if (leapyear(y))
      return 29;
    else
      return 28;
}

When you use the above definitions in your implementation (i.e. Date.cpp file), the user shouldn't even know they're there! Your definition for class Date should be split into Date.h and Date.cpp. When you put it together with part4.cpp it should be compiled like this:

g++ -o agecomp part4.cpp Date.cpp

You should get a program that computes the number of days between when I was born and when you were born. The driver program part4.cpp (provided below) should be your guide as to the proper interface for your Date class.

part4.cpp

/***********************************************************
* Program reads user's birthdate and determines how many
* days older Maj Hawkins is than the user.  The date is not my real
* birthday, because using my real birthday would be PII.
***********************************************************/
#include "Date.h"
#include <iostream>
using namespace std;
int main() {
  // Set my "birthday" and read yours
  Date MyBD(5,25,1979); // May 25, 1979 is day the movie "Alien" was released
  Date YrBD;
  cout << "What was your birth date? ";
  YrBD.readIn(cin);

  // If I'm older, compute by how many days and print it
  if (YrBD.before(MyBD))
    cout << "You're older than I!" << endl;
  else {
    int count = 0;
    for(Date T = MyBD; T.before(YrBD); T.inc())
      count++;
    cout << "I'm " << count << " days older than you!" << endl;
  }

  return 0;
}

Deliverables

Due: 2359 evening before Lab 4

Submit part1.cpp, part2.cpp, Point.h, Point.cpp, part3.txt, Date.h and Date.cpp to the the submisison website: submit.cs.usna.edu

~/bin/submit -c=SI221 -p=Lab03 part1.cpp part2.cpp Point.h Point.cpp part3.txt Date.h Date.cpp