
|
Here is the account code
Reading Covered: 9,10 Reading Assigned: 11-14 Data AbstractionWe may not know what "Object Oriented" programming is, but there are certain aspects that are commonly considered Object Oriented which are very important. Data abstraction is one of them. The idea is that you often want to think of data in the world, not in terms of ints and chars, but in terms of whatever occurs most naturally for you. C++ allows you to define your own types, often called user-defined types, or data abstraction. The idea is that you define some new type (a class) and then you can declare variables of that type just like the built-in types (int, char, etc...).ClassesSo how do we write these little objects of joy? A sample class with a function that uses it is below:
#include <iostream.h>
// The declaration of our new type.
class box_car
{
public: // Public means that anyone can access that value.
double height, width, length; // No initialization:
char SerialNumber[8]; // it is not allowed inside class declarations
};
double // returns the volume of the box car.
volume(box_car inBoxCar)
{
return inBoxCar.height * inBoxCar.width * inBoxCar.length;
}
main()
{
box_car theBoxCar;
cout << "Input boxcar length: ";
cin >> theBoxCar.length;
cout << "Input boxcar height: ";
cin >> theBoxCar.height;
cout << "Input boxcar width: ";
cin >> theBoxCar.width;
cout << "Input boxcar serial number (7 chars max): ";
cin >> theBoxCar.SerialNumber;
cout << "The boxcar volume is: "
<< volume(theBoxCar);
}
Notice that you need to initialize all of the variables of your type,
and that you use them with the period operator. Don't forget to
initialize all of the data members of your class. Also the class
definition does not execute any code so you can stick it in a header
file so that code in other files can use your class. You can now use
your class just like any other type, e.g. you can write functions that
use it (like above) and you can allocate variables of it, just like
any other type, either statically or dynamically. For example:
int * theBoxCar = new box_car; Data hiding through accessor functions.In the above function, we are always dealing with the member variables directly. This can be annoying because anyone can access them, and change them. This is because they are declared public. We can hide them by using the private keyword. But you ask, what good does a private keyword do us, if we just can't see the values then? Well, there are ways to write functions that are only good for accessing your type. They are called accessor functions, and allow you to read data from or write data into your class. (These are a type of member function. We will talk about other member functions later.) In order to write the above using data hiding, we implement it as follows:
#include <iostream.h>
#include <string.h>
// The declaration of our new type.
class box_car
{
pivate: // Our hidden data.
double height, width, length; // No initialization:
char SerialNumber[8]; // it is not allowed inside class declarations
public: // The accessor functions:
// These all set values:
void SetHeight(double newHeight); // Note that the accesors are just
void SetWidth(double newWidth); // regular function declarations
void SetLength(double newLength); // inside of a class declaration.
void SetName(char newName[]);
// This reads values:
double Volume(); // Now the only thing that can be read is the volume.
};
// so, now that we have all of these function declarations
// (prototypes), how do we define them? Just like normal, except that we
// have to tell the compiler which class it is a member of, and then
// that function has local access to all of the members.
double // returns the volume of the box car.
box_car::Volume()
{
return height * width * length;
}
void SetHeight(double newHeight)
{
height = newHeight;
}
void SetWidth(double newWidth)
{
width = newWidth;
}
void SetLength(double newLength)
{
length = newLength;
}
void SetName(char newName[])
{
strcpy(SerialNumber, newName);
}
main()
{
box_car theBoxCar;
double numberBuffer;
char stringBuffer[8];
cout << "Input boxcar length: ";
cin >> numberBuffer;
theBoxCar.setLength(numberBuffer);
cout << "Input boxcar height: ";
cin >> numberBuffer;
theBoxCar.setHeight(numberBuffer);
cout << "Input boxcar width: ";
cin >> numberBuffer;
theBoxCar.setWidth(numberBuffer);
cout << "Input boxcar serial number (7 chars max): ";
cin << stringBuffer;
theBoxCar.SetName(stringBuffer);
cout << "The boxcar volume is: "
<< theBoxCar.Volume();
}
This lecture covers some more features of classes. Mostly we look at
more uses of member functions, including constructors and
destructors. We also look at more interesting uses of accessor
functions.
Reading Covered: 11-14 Reading Assigned: Look through 9-14 again and make sure you understand it. Read 25-28, 30. (You'll use 25 on the homework, and we probably won't go over 26 in class. That is just for kicks. Also, If you want to know how that switch statment that I used in the code for the homework works, you can read about it in chapter 30.) A quick reminder of classes
More member functionsLast time we talked about accessor functions, which are one type of member function. There are also many other types of useful member functions. The constructor and the desreuctor are two very important member functions.The Constructor member functionOne special member function allows you to do work on the data as soon as your class is instantialted, the constructor. This function has no return value, not even void, and can be overloaded. The base constructor that is called automatically is the default constructor, it has no parameters. This allows you to set all the member variables to default types. Be careful, because this is not initalization, but just setting the values to default types. This means that you can not just set strings equal to constant strings, you need to use strcpy like in the accessor function from last time. An example class with constructors is shown below:
class box_car
{
private:
double height, width, length;
char SerialNumber[8];
public:
box_car(); // The default constructor.
box_car(double,double,double); // Another constructor
// ... The accessors go here
};
// The default constructor sets values that are reasonable.
box_car::box_car()
{
height = 11.0, width = 9.0, length = 40.0;
SetName("No name");
}
box_car::box_car(
double initHeight, // Inital values that you can set when
double initWidth, // using your new type.
double initLength)
{
height = initHeight;
width = initWidth;
length = initLength;
SetName("No name");
}
Now that we have our declarations and definitions of the constructors,
how do we use them? Well the default constructor was already being
used. The default constructor is used in the basic variable
declaration step. In order to use a different constructor, you need
to change the variable declaration a bit to make it look like a
function call:
box_car car1; // Uses default constructor.
box_car car2(3.5, 9.0, 40.0); // uses other constructor.
box_car myBoxCarArray[6]; // Uses default constructor on each
// element of the array.
box_car * myBoxCarArray2[x]; // Uses default constructor on each
// element of the array.
We will look at how to use other constructors on individual elements
of an array later. Much later.
What winston calls reader and writer functions are just accessor functions. How to benifit from data abstractiona.k.a. Why do we use classes? The first and most important element of data abstraction is that when using the accessor functions, you do not know what is happening. If the internals of the class change at a later point, as long as the "interface" remains the same the class can still be used for exactly the same purpose, in the same way, with no affect on the rest of your program. This is why you want to use accessor functions instead of just directly changing the member variables.This is also why when you are creating a class you need to make constructor and accessor functions. If you hide all of the data behind these functions, you are said to be making a data abstraction layer. This is crucial to good "object oriented" programming. Another advantage is that you can provide more functionality from your class by just adding more functions, without losing the ability to acces the old functionality. All of these points provide the following bullets:
|