OBJECTS AND CLASSES In this chapter you learn Procedural and Object-Oriented Programming Abstraction and Classes Class Constructors and Destructors Knowing Your Objects: The this Pointer
Trang 1{ cout << "Bad input Please enter a number: ";
cin.clear();
while (cin.get() != '\n') continue;
} cout << "Value = " << x << endl;
return 0;
}
.4: Rewrite the following so that it uses using-declarations instead of the using-directive
#include <iostream>
using namespace std;
int main() {
double x;
cout << "Enter value: ";
while (! (cin >> x) ) {
cout << "Bad input Please enter a number: ";
cin.clear();
while (cin.get() != '\n') continue;
} cout << "Value = " << x << endl;
return 0;
}
.5: The average(3,6) function returns an int average of the two int arguments when called in one file, and it returns a double average of the two int arguments when called in a second file in the same program How could you set this up?
Trang 2.6: What will the following two-file program display?
// file1.cpp
#include <iostream>
using namespace std;
void other();
void another();
int x = 10;
int y;
int main() {
cout << x << endl;
{ int x = 4;
cout << x << endl;
cout << y << endl;
} other();
another();
return 0;
} void other() {
int y = 1;
cout << "Other: " << x << "," << y << endl;
} // file 2.cpp
#include <iostream>
using namespace std;
extern int x;
namespace {
int y = -4;
} void another()
Trang 3{ cout << "another(): " << x << ", " << y << endl;
}
.7: What will the following program display?
#include <iostream>
using namespace std;
void other();
namespace n1 {
int x = 1;
} namespace n2 {
int x = 2;
} int main() {
using namespace n1;
cout << x << endl;
{ int x = 4;
cout << x << ", " << n1::x << ", " << n2::x << endl;
} using n2::x;
cout << x << endl;
other();
return 0;
} void other() {
using namespace n2;
cout << x << endl;
{ int x = 4;
Trang 4cout << x << ", " << n1::x << ", " << n2::x << endl;
} using n2::x;
cout << x << endl;
}
Programming Exercises
1: Here is a header file:
// golf.h for pe8-3.cpp const int Len = 40;
struct golf {
char fullname[Len];
int handicap;
};
// non-interactive version:
// function sets golf structure to provided name, handicap // using values passed as arguments to the function void setgolf(golf & g, const char * name, int hc);
// interactive version:
// function solicits name and handicap from user // and sets the members of g to the values entered // returns 1 if name is entered, 0 if name is empty string int setgolf(golf & g);
// function resets handicap to new value void handicap(golf & g, int hc);
// function displays contents of golf structure void showgolf(const golf & g);
Note that setgolf() is overloaded Using the first version would look like this:
Trang 5golf ann;
setgolf(ann, "Ann Birdfree", 24);
The function call provides the information that's stored in the ann structure
Using the second version would look like this:
golf andy;
setgolf(andy);
The function would prompt the user to enter the name and handicap and store them in the andy structure This function could (but doesn't need to) use the first version internally
Put together a multifile program based on this header One file, named golf.cpp, should provide suitable function definitions to match the prototypes in the header file A second file should contain main() and demonstrate all the features of the prototyped functions For example, a loop should solicit input for
an array of golf structures and terminate when the array is full or the user enters
an empty string for the golfer's name The main() function should use only the prototyped functions to access the golf structures
2: Here is a namespace:
namespace SALES {
const int QUARTERS = 4;
struct Sales {
double sales[QUARTERS];
double average;
double max;
double min;
};
// copies the lesser of 4 or n items from the array ar // to the sales member of s and computes and stores the
Trang 6// average, maximum, and minimum values of the entered items;
// remaining elements of sales, if any, set to 0 void setSales(Sales & s, const double ar[], int n);
// gathers sales for 4 quarters interactively, stores them // in the sales member of s and computes and stores the // average, maximum, and minumum values
void setSales(Sales & s);
// display all information in structure s void showSales(const Sales & s);
}
Write a three-file program based on this namespace The first file should be a header file containing the namespace The second file should be a source code file extending the namespace to provide definitions for the three prototyped functions The third file should declare two Sales objects It should use the interactive version of setSales() to provide values for one structure and the non-interactive version of setSales() to provide values for the second structure
It should display the contents of both structures by using showSales()
CONTENTS
Trang 7Chapter 10 OBJECTS AND CLASSES
In this chapter you learn
Procedural and Object-Oriented Programming Abstraction and Classes
Class Constructors and Destructors Knowing Your Objects: The this Pointer
An Array of Objects Class Scope
An Abstract Data Type Summary
Review Questions Programming Exercises
Object-oriented programming (OOP) is a particular conceptual approach to designing
programs, and C++ has enhanced C with features that ease the way to applying that
approach The most important OOP features are these:
Abstraction
Encapsulation and data hiding
Polymorphism
Inheritance
Reusable code
The class is the single most important C++ enhancement for implementing these features
and tying them together This chapter begins our examination of classes It explains
abstraction, encapsulation, and data hiding, and shows how classes implement these
features It discusses how to define a class, provide a class with public and private
sections, and create member functions that work with the class data Also, the chapter
acquaints you with constructors and destructors, which are special member functions for
Trang 8creating and disposing of objects belonging to a class Finally, you meet the this pointer,
an important component of some class programming The following chapters extend the
discussion to operator overloading (another variety of polymorphism) and inheritance, the
basis for reusing code
Procedural and Object-Oriented Programming
Although we have occasionally explored the OOP perspective on programming, we've
usually stuck pretty close to the standard procedural approach of languages such as C,
Pascal, and BASIC Let's look at an example that clarifies how the OOP outlook differs
from that of procedural programming
As the newest member of the Genre Giants softball team, you've been asked to keep the
team statistics Naturally, you turn to your computer for help If you were a procedural
programmer, you might think along these lines:
Let's see, I want to enter the name, times at bat, number of hits, batting averages (for those who don't follow baseball or softball, the batting average
is the number of hits divided by the player's official number of times at bat;
an at bat terminates when a player gets on base or makes an out, but certain events, such as getting a walk, don't count as official times at bat), and all those other great basic statistics for each player Wait, the computer
is supposed to make life easier for me, so let's have it figure out some of that stuff, such as the batting average Also, I want the program to report the results How should I organize this? I guess I should do things right and use functions Yeah, I'll make main() call a function to get the input, call a
function to make the calculations, and then call a function to report the results Hmmm, what happens when I get data from the next game? I don't want to start from scratch again Okay, I can add a function to update the statistics Golly, maybe I'll need a menu in main() to select between entering, calculating, updating, and showing the data Hmmm—how am I going to represent the data? I could use an array of strings to hold the players' names, another array to hold the at bats for each player, yet another array to hold the hits, and so on No, that's dumb I can design a structure to hold all the information for a single player and then use an array
of those structures to represent the whole team
In short, you first concentrate on the procedures you will follow and then think about how to
Trang 9represent the data (Note: So that you don't have to keep the program running the whole
season, you probably also want to be able to save data to a file and read data from a file
But as we haven't covered files yet, we ignore that complication for now.)
Now let's see how your perspective changes when you don your OOP hat (an attractive
polymorphic design) You begin by thinking about the data Furthermore, you think about
the data not only in terms of how to represent it, but in terms of how it's to be used:
Let's see—what am I keeping track of? A ball player, of course So, I want
an object that represents the whole player, not just her batting average or times at bat Yeah, that'll be my fundamental data unit, an object
representing the name and statistics for a player I'll need some methods to handle this object Hmmm, I guess I need a method to get basic information into this unit The computer should calculate some of the stuff, like the batting averages—I can add methods to do calculations And the program should do those calculations automatically, without the user having to remember to ask to have them done Also, I'll need methods for updating and displaying the information So, the user gets three ways to interact with the data: initialization, updating, and reporting That's the user interface
In short, you concentrate on the object as the user perceives it, thinking about the data you
need to describe the object and the operations that will describe the user's interaction with
the data After you develop a description of that interface, you move on to decide how to
implement the interface and data storage Finally, you put together a program to use your
new design
Abstraction and Classes
Life is full of complexities, and one way we cope with complexity is to frame simplifying
abstractions You are a collection of over an octillion atoms Some students of the mind
would say your mind is a collection of semiautonomous agents But it's much simpler to
think of yourself as a single entity In computing, abstraction is the crucial step of
representing information in terms of its interface with the user That is, you abstract the
essential operational features of a problem and express a solution in those terms In the
softball statistics example, the interface describes how the user initializes, updates, and
displays the data From abstraction, it is a short step to the user-defined type, which in C++
is a class design that implements that interface
Trang 10What's a Type?
Let's think a little more about what constitutes a type For example, what is a nerd? If you
subscribe to the popular stereotype, you may think of a nerd in visual terms—thick,
black-rimmed glasses, pocket protector full of pens, and so on After a little reflection, you
might conclude that a nerd is better defined operationally, for example, in how he or she
responds to an awkward social situation We have a similar situation, if you don't mind
stretched analogies, with a procedural language like C At first, you tend to think of a data
type in terms of its appearance—how it is stored in memory A char, for example, is one
byte of memory, and a double often is eight bytes of memory But a little reflection leads
us to conclude that a data type also is defined in terms of the operations that can be
performed upon it For example, the int type can use all the arithmetic operations You can
add, subtract, multiply, and divide integers You also can use the modulus operator (%)
with them
On the other hand, consider pointers A pointer might very well require the same amount of
memory as an int It might even be represented internally as an integer But a pointer
doesn't allow the same operations that an integer does You can't, for example, multiply
two pointers by each other The concept makes no sense, so C++ doesn't implement it
Thus, when you declare a variable as an int or as a pointer-to-float, you're not just
allocating memory—you also are establishing which operations can be performed with the
variable In short, specifying a basic type does two things:
It determines how much memory is needed for a data object
It determines what operations, or methods, can be performed using the data object
For built-in types, this information is built in to the compiler But when you define a
user-defined type in C++, you have to provide the same kind of information yourself In
exchange for this extra work, you gain the power and flexibility to custom fit new data types
to match real-world requirements
The Class
The class is the C++ vehicle for translating an abstraction to a user-defined type It
combines data representation and methods for manipulating that data into one neat
package Let's look at a class that represents stocks
Trang 11First, we have to think a bit about how to represent stocks We could take one share of
stock as the basic unit and define a class to represent a share However, that implies that
you would need 100 objects to represent 100 shares, and that's not practical Instead, let's
represent a person's current holdings in a particular stock as a basic unit The number of
shares owned would be part of the data representation A realistic approach would have to
maintain records of such things as initial purchase price and date of purchase, for tax
purposes Also, it would have to manage events such as stock splits That seems a bit
ambitious for our first effort at defining a class, so let's take an idealized, simplified view of
matters In particular, let's limit the operations we can perform to the following:
Acquire stock in a company
Buy more shares of the same stock
Sell stock
Update the per-share value of a stock
Display information about the holdings
We can use this list to define the public interface for the stock class, leaving additional
features as exercises for the interested To support this interface, we need to store some
information Again, we use a simplified approach For example, we won't worry about the
standard U.S practice of evaluating stocks in multiples of eighths of a dollar (Apparently
the New York Stock Exchange must have seen this simplification in a previous edition of
the book, for it has decided to change over to the system used here.) We will store the
following information:
Name of company
Number of stocks owned
Value of each share
Total value of all shares
Next, let's define the class Generally, a class specification has two parts:
A class declaration, which describes the data component, in terms of data members, and the public interface, in terms of member functions