1. Trang chủ
  2. » Công Nghệ Thông Tin

Absolute C++ (4th Edition) part 25 docx

10 202 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 216,72 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Defining a class so that the implementation of the member functions and the imple-mentation of the data in objects are not known, or is at least irrelevant, to the program-mer who uses t

Trang 1

A programmer who uses a class also should not need to know how the data of the class is implemented The implementation of the data should be as hidden as the imple-mentation of the member functions In fact, it is close to impossible to distinguish between hiding the implementation of the member functions and the implementation

of the data To a programmer, the class DayOfYear (Display 6.3) has dates as data, not numbers The programmer should not know or care whether the month March is implemented as the int value 3, the quoted string "March", or in some other way

Defining a class so that the implementation of the member functions and the imple-mentation of the data in objects are not known, or is at least irrelevant, to the program-mer who uses the class is known by a number of different terms The most common

terms used are information hiding, data abstraction, and encapsulation, each of

which means that the details of the implementation of a class are hidden from the pro-grammer who uses the class This principle is one of the main tenets of object-oriented programming (OOP) When discussing OOP, the term that is used most frequently is

encapsulation One of the ways to apply this principle of encapsulation to your class

definitions is to make all member variables private, which is what we discuss in the next subsection

Look back at the definition of the type DayOfYear given in Display 6.3 In order to use that class, you need to know that there are two member variables of type int that are named month and day This violates the principle of encapsulation (information hiding) that we discussed in the previous subsection Display 6.4 is a rewritten version of the class DayOfYear that better conforms to this encapsulation principle

Notice the words private: and public: in Display 6.4 All the items that follow the word private: (in this case the member variables month and day) are said to be

private, which means that they cannot be referenced by name anyplace except within

the definitions of the member functions of the class DayOfYear For example, with this changed definition of the class DayOfYear, the following two assignments and other indicated code are no longer permitted in the main function of the program and are not permitted in any other function definition, except for member functions of the class DayOfYear:

DayOfYear today; //This line is OK.

today.month = 12;//ILLEGAL today.day = 25;//ILLEGAL cout << today.month;//ILLEGAL cout << today.day;//ILLEGAL

if (today.month == 1) //ILLEGAL cout << "January";

Once you make a member variable a private member variable, there is no way to change its value (or to reference the member variable in any other way) except by using one of the member functions That means that the compiler will enforce the hiding of

encapsu-lation

private:

private member variable

Trang 2

Display 6.4 Class with Private Members (part 1 of 3)

1 #include <iostream>

2 #include <cstdlib>

3 using namespace std;

4 class DayOfYear

6 public:

7 void input( );

8 void output( );

9 void set( int newMonth, int newDay);

10 //Precondition: newMonth and newDay form a possible date.

11 void set( int newMonth);

12 //Precondition: 1 <= newMonth <= 12

13 //Postcondition: The date is set to the first day of the given month.

14 int getMonthNumber( ); //Returns 1 for January, 2 for February, etc.

15 int getDay( );

16 private:

17 int month;

18 int day;

20 int main( )

22 DayOfYear today, bachBirthday;

23 cout << "Enter today’s date:\n";

24 today.input( );

25 cout << "Today’s date is ";

26 today.output( );

27 cout << endl;

28 bachBirthday.set(3, 21);

29 cout << "J S Bach’s birthday is ";

30 bachBirthday.output( );

31 cout << endl;

32 if ( today.getMonthNumber( ) == bachBirthday.getMonthNumber( ) &&

33 today.getDay( ) == bachBirthday.getDay( ) )

34 cout << "Happy Birthday Johann Sebastian!\n";

35 else

36 cout << "Happy Unbirthday Johann Sebastian!\n";

37

38 return 0;

40 //Uses iostream and cstdlib:

41 void DayOfYear::set( int newMonth, int newDay)

Private members

This is an improved version

of the class DayOfYear that we gave

in Display 6.3.

Note that the function name set is overloaded You can overload a member function just like you can overload any other function.

Trang 3

Display 6.4 Class with Private Members (part 2 of 3)

43 if ((newMonth >= 1) && (newMonth <= 12))

44 month = newMonth;

45 else

47 cout << "Illegal month value! Program aborted.\n";

48 exit(1);

50 if ((newDay >= 1) && (newDay <= 31))

51 day = newDay;

52 else

54 cout << "Illegal day value! Program aborted.\n";

55 exit(1);

58 //Uses iostream and cstdlib:

59 void DayOfYear::set( int newMonth)

61 if ((newMonth >= 1) && (newMonth <= 12))

62 month = newMonth;

63 else

65 cout << "Illegal month value! Program aborted.\n";

66 exit(1);

68 day = 1;

70

71 int DayOfYear::getMonthNumber( )

73 return month;

75 int DayOfYear::getDay( )

77 return day;

79 //Uses iostream and cstdlib:

80 void DayOfYear::input( )

82 cout << "Enter the month as a number: ";

83 cin >> month;

84 cout << "Enter the day of the month: ";

85 cin >> day;

Mutator functions

Accessor functions

Private members may

be used in member function definitions (but not elsewhere).

Trang 4

the implementation of the data for the class DayOfYear If you look carefully at the pro-gram in Display 6.4, you will see that the only place the member variable names month and day are used is in the definitions of the member functions There is no reference to today.month, today.day, bachBirthday.month, or bachBirthday.day anyplace outside the definitions of member functions

All the items that follow the word public: (in this case the member functions) are

said to be public, which means that they can be referenced by name anyplace There

are no restrictions on the use of public members

Any member variables can be either public or private Any member functions can be

public or private However, normal good programming practices require that all

mem-ber variables be private and that typically most memmem-ber functions be public

You can have any number of occurrences of public and private access specifiers in

a class definition Every time you insert the label

public :

the list of members changes from private to public Every time you insert the label

private :

the list of members changes back to being private members You need not have just one public and one private group of members However, it is common to have just one public section and one private section

Display 6.4 Class with Private Members (part 3 of 3)

86 if ((month < 1) || (month > 12) || (day < 1) || (day > 31))

88 cout << "Illegal date! Program aborted.\n";

89 exit(1);

92 void DayOfYear::output( )

93 <The rest of the definition of DayOfYear::output is given in Display 6.3.>

SAMPLE DIALOGUE

Enter today’s date:

Enter the month as a number: 3

Enter the day of the month: 21

Today’s date is March 21

J S Bach’s birthday is March 21

Happy Birthday Johann Sebastian!

public:

public

member

variable

Trang 5

There is no universal agreement about whether the public members should be listed first or the private members should be listed first The majority seem to prefer listing the public members first This allows for easy viewing of the portions programmers using the class actually get to use You can make your own decision on what you wish

to place first, but the examples in the book will go along with the majority and list the public members before the private members

In one sense C++ seems to favor placing the private members first If the first group

of members has neither the public: nor the private: specifier, then members of that group will automatically be private You will see this default behavior used in code and should be familiar with it However, we will not use it in this book

You should always make all member variables in a class private You may sometimes need to do something with the data in a class object, however The member functions will allow you to do many things with the data in an object, but sooner or later you will want or need to do something with the data for which there is no member function

How can you do anything new with the data in an object? The answer is that you can do anything you might reasonably want, provided you equip your classes with suitable accessor and mutator functions These are member functions that allow you to access

and change the data in an object in a very general way Accessor functions allow you to

read the data In Display 6.4, the member functions getMonthNumber and getDay are accessor functions The accessor functions need not literally return the values of each member variable, but they must return something equivalent to those values For exam-ple, for a class like DayOfYear, you might have an accessor function return the name of the month as some sort of string value, rather than return the month as a number

Mutator functions allow you to change the data In Display 6.4, the two functions

named set are mutator functions It is traditional to use names that include the word get for accessor functions and names that include the word set for mutator functions

(The functions input and output in Display 6.4 are really mutator and accessor

func-tions, respectively, but I/O is such a special case that they are usually just called I/O functions rather than accessor or mutator functions.)

Your class definitions should always provide an adequate collection of accessor and mutator functions

It may seem that accessor and mutator functions defeat the purpose of making mem-ber variables private, but that is not so Notice the mutator function set in Display 6.4

It will not allow you to set the month member variable to 13 or to any number that does not represent a month Similarly, it will not allow you to set the day member variable to any number that is not in the range 1 to 31 (inclusive) If the variables were public you could set the data to values that do not make sense for a date (As it is, you can still set the data to values that do not represent a real date, such as February 31, but it would be easy to exclude these dates as well We did not exclude these dates to keep the example simple.) With mutator functions, you can control and filter changes to the data

accessor function

mutator function

Trang 6

Self-Test Exercises

12 Suppose your program contains the following class definition, class Automobile

{ public : void setPrice( double newPrice);

void setProfit( double newProfit);

double getPrice( );

private : double price;

double profit;

double getProfit( );

};

and suppose the main function of your program contains the following declaration and that the program somehow sets the values of all the member variables to some values:

Automobile hyundai, jaguar;

Which of the following statements are then allowed in the main function of your program? hyundai.price = 4999.99;

jaguar.setPrice(30000.97);

double aPrice, aProfit;

aPrice = jaguar.getPrice( );

aProfit = jaguar.getProfit( );

aProfit = hyundai.getProfit( );

hyundai = jaguar;

13 Suppose you change Self-Test Exercise 12 so that in the definition of the class Automobile all member variables are public instead of private How would this change your answer to the question in Self-Test Exercise 12?

14 Explain what public: and private: mean in a class definition

15 a How many public: sections are required in a class for the class to be useful?

b How many private: sections are required in a class?

S EPARATE I NTERFACE AND I MPLEMENTATION

The principle of encapsulation says that you should define classes so that a programmer who uses the class need not be concerned with the details of how the class is implemented The programmer who uses the class need only know the rules for how to use the class The rules for how to use the class are known as the iiiin n ntttteeeerrrrffffaaa acccceeee or A A APPPPIIII There is some disagreement on exactly what the initials API stand for, but it is generally agreed that they stand for something like application programmer

interface

API

Trang 7

interface or abstract programming interface or something similar In this book we will call these rules the interface for the class It is important to keep in mind a clear distinction between the interface and the implementation of a class If your class is well designed, then any programmer who uses the class need only know the interface for the class and need not know any details of the implementation of the class A class whose interface and implementation are separated in this way is sometimes called an abstract data type (ADT) or a nicely encapsulated class In Chapter 11

we will show you how to separate the interface and implementation by placing them in different files, but the important thing is to keep them conceptually separated.

For a C++ class, the iiiin n ntttteeeerrrrffffaaa acccceeee consists of two sorts of things: the comments, usually at the begin-ning of the class definition, that tell what the data of the object is supposed to represent, such as

a date or bank account or state of a simulated car wash; and the public member functions of the class along with the comments that tell how to use these public member functions In a well-designed class, the interface of the class should be all you need to know in order to use the class

in your program

The iiiim m mp plllleeeem p meeeenn m nttttaaa n attttiiiiooo onn n of a class tells how the class interface is realized as C++ code The implemen- n tation consists of the private members of the class and the definitions of both the public and pri-vate member functions Although you need the implementation in order to run a program that uses the class, you should not need to know anything about the implementation in order to write the rest of a program that uses the class; that is, you should not need to know anything about the implementation in order to write the main function of the program and to write any nonmember functions or other classes used by the main function

The most obvious benefit you derive from cleanly separating the interface and implementation of your classes is that you can change the implementation without having to change the other parts

of your program On large programming projects this division between interface and implemen-tation will facilitate dividing the work among different programmers If you have a well-designed interface, then one programmer can write the implementation for the class while other program-mers write the code that uses the class Even if you are the only programmer working on a project, you have divided one larger task into two smaller tasks, which makes your program easier to design and to debug.

A T EST FOR E NCAPSULATION

If your class definition produces an ADT (that is, if it properly separates the interface and the implementation), then you can change the implementation of the class (that is, change the data representation and/or change the implementation of some member functions) without needing

to change any (other) code for any program that uses the class definition This is a sure test for whether you have defined an ADT or just some class that is not properly encapsulated.

For example, you can change the implementation of the class DayOfYear in Display 6.4 to the following and no program that uses this class definition would need any changes:

class DayOfYear {

implemen-tation

Trang 8

public : void input( );

void output( );

void set( int newMonth, int newDay);

//Precondition: newMonth and newDay form a possible date.

//Postcondition: The date is reset according to the arguments.

void set( int newMonth);

//Precondition: 1 <= newMonth <= 12 //Postcondition: The date is set to first day of the month.

int getMonthNumber( );

//Returns 1 for January, 2 for February, etc.

int getDay( );

private : char firstLetter;//of month char secondLetter;//of month char thirdLetter;//of month int day;

};

In this version, a month is represented by the first three letters in its name, such as ’J’ , ’a’ , and

’n’ for January The member functions should also be rewritten, of course, but they can be rewritten to behave exactly as they did before For example, the definition of the function get-MonthNumber might start as follows:

int DayOfYear::getMonthNumber( ) {

if (firstLetter == ’J’ && secondLetter == ’a’

&& thirdLetter == ’n’) return 1;

if (firstLetter == ’F’ && secondLetter == ’e’

&& thirdLetter == ’b’) return 2;

.

This would be rather tedious, but not difficult.

Structures are normally used with all member variables public and with no member functions However, in C++ a structure can have private member variables and both public and private member functions Aside from some notational differences, a C++ structure can do anything a class can do Having said this and satisfied the “truth in adver-tising” requirement, we advocate that you forget this technical detail about structures If

Trang 9

C LASSES AND O BJECTS

A class is a type whose variables can have both member variables and member functions The syntax for a class definition is given below.

S YNTAX

class Class_Name

{

.

public :

Member_SpecificationN+1 Member_SpecificationN+2

.

private :

Member_Specification_1 Member_Specification_2

.

Member_SpecificationN

};

Each Member_Specification_i is either a member variable declaration or a member function declaration (prototype).

Additional public: and private: sections are permitted If the first group of members does not have either a public: or a private: label, then it is the same as if there were a private:

before the first group.

E XAMPLE

class Bicycle {

public : char getColor( );

int numberOfSpeeds( );

void set( int theSpeeds, char theColor);

private : int speeds;

char color;

};

Once a class is defined, an object variable (variable of the class type) can be declared in the same way as variables of any other type For example, the following declares two object variables of type Bicycle :

Bicycle myBike, yourBike;

Public members

Private members

Do not forget this semicolon.

Trang 10

Self-Test Exercises

Tip

you take this technical detail seriously and use structures in the same way that you use classes, then you will have two names (with different syntax rules) for the same con-cept On the other hand, if you use structures as we described them, then you will have

a meaningful difference between structures (as you use them) and classes; and your usage will be the same as that of most other programmers

One difference between a structure and a class is that they differ in how they treat an initial group of members that has neither a public nor a private access specifier If the first group of members in a definition is not labeled with either public: or private:, then a structure assumes the group is public, whereas a class would assume the group is private

T HINKING O BJECTS

If you have not programmed with classes before, it can take a little while to get the feel of pro-gramming with them When you program with classes, data rather than algorithms takes center stage It is not that there are no algorithms However, the algorithms are made to fit the data, as opposed to designing the data to fit the algorithms It’s a difference in point of view In the extreme case, which is considered by many to be the best style, you have no global functions at all, only classes with member functions In this case, you define objects and how the objects inter-act, rather than algorithms that operate on data We will discuss the details of how you accom-plish this throughout this book Of course, you can ignore classes completely or relegate them to a minor role, but then you are really programming in C, not C++.

16 When you define a C++ class, should you make the member variables public or private? Should you make the member functions public or private?

17 When you define a C++ class, what items are considered part of the interface? What items are considered part of the implementation?

■ A structure can be used to combine data of different types into a single (compound) data value

■ A class can be used to combine data and functions into a single (compound) object

■ A member variable or a member function for a class can be either public or private

If it is public, it can be used outside the class If it is private, it can be used only in the definition of a member function

Chapter Summary

Ngày đăng: 04/07/2014, 05:21