Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ For Dummies (2004) [eng].pdf
Скачиваний:
84
Добавлен:
16.08.2013
Размер:
8.09 Mб
Скачать

Chapter 15: Protecting Members: Do Not Disturb 205

The addition of the member function grade(float) allows the application to set the gpa. Notice, however, that the class still hasn’t given up control completely. The application can’t set gpa to any old value; only a gpa in the legal range of values (from 0 through 4.0) is accepted.

Thus, Student class has provided access to an internal data member without abdicating its responsibility to make sure that the internal state of the class is valid.

Using a class with a limited interface

A class provides a limited interface. To use a class, all you need (or want) to know are its public members, what they do, and what their arguments are. This can drastically reduce the number of things you need to master — and remember to use the class.

As conditions change or as bugs are found, you want to be able to change the internal workings of a class. Changes to those details are less likely to require changes in the external application code if you can hide the internal workings of the class.

A second, perhaps more important reason, lies in the limited ability of humans (I can’t speak for dogs and cats) to keep a large number of things in their minds at any given instant. Using a strictly defined class interface allows the pro­ grammer to forget the details that go on behind it. Likewise, a programmer building the class need not concentrate to quite the same degree on exactly how each of the functions is being used.

Giving Non-Member Functions

Access to Protected Members

Occasionally, you want a non-member function to have access to the pro­ tected members of a class. You do so by declaring the function to be a friend of the class by using the keyword friend.

Sometimes, an external function can use direct access to a data member. I know this appears to break the strictly defined, well-sealed-off class interface position that I’ve been advocating, but just consider the following. First, including a friend function is, in effect, adding that function to the interface (that’s why a class shouldn’t have too many friends). You’re okay as long as you attempt to treat this function as a normal function that, oh yeah, happens to have direct access. Second, providing a public access method that acts as

206 Part III: Introduction to Classes

a thin veil over a data member doesn’t do anything to abstract away class details. Such a thin veneer function fulfills the letter of the law, but not the spirit.

The friend declaration appears in the class that contains the protected member. The friend declaration is like a prototype declaration in that it includes the extended name and the return type. In the following example, the function initialize() can now access anything it wants in Student:

class Student

{

friend void initialize(Student*); public:

// same public members as before...

protected:

int semesterHours; // hours earned toward graduation float gpa;

};

//the following function is a friend of Student

//so it can access the protected members

void initialize(Student *pS)

{

pS->gpa = 0; // this is now legal...

pS->semesterHours = 0; // ...when it wasn’t before

}

A single function can be declared a friend of two classes at the same time. Although this can be convenient, it tends to bind the two classes together. This binding of classes is normally considered bad because it makes one class dependent on the other. If the two classes naturally belong together, however, it’s not all bad, as shown here:

class Student; // forward declaration class Teacher

{

friend void registration(Teacher& t, Student& s); public:

void assignGrades(); protected:

int noStudents; Student *pList[100];

};

class Student

{

friend void registration(Teacher& t, Student& s); public:

// same public members as before...

protected: Teacher *pT;

int semesterHours; // hours earned toward graduation float gpa;

};

Chapter 15: Protecting Members: Do Not Disturb 207

void registration(Teacher& t, Student& s)

{

//initialize the Student object s.semesterHours = 0;

s.gpa = 0;

//if there’s room...

if (t.noStudents < 100)

{

// ...add it onto the end of the list t.pList[t.noStudents] = &s; t.noStudents++;

}

}

In this example, the registration() function can reach into both the Student and Teacher classes to tie them together at registration time, with­ out being a member function of either one.

The first line in the example declares the class Student, but none of its mem­ bers. This is called a forward declaration and just defines the name of the class so that other classes, such as Teacher, can define a pointer to it. Forward references are necessary when two classes refer to each other.

A member function of one class may be declared a friend of another class, as shown here:

class Teacher

{

// ...other members as well...

public:

void assignGrades();

};

class Student

{

friend void Teacher::assignGrades(); public:

// same public members as before...

protected:

int semesterHours; // hours earned toward graduation float gpa;

};

void Teacher::assignGrades()

{

// can access protected members of Teacher from here

}

Unlike in the non-member example, the member function assignGrades() must be declared before the class Student can declare it to be a friend.

208 Part III: Introduction to Classes

An entire class can be named a friend of another. This has the effect of making every member function of the class a friend:

class Student; // forward declaration class Teacher

{

protected:

int noStudents; Student *pList[100]; public:

void assignGrades(); };

class Student

{

friend class Teacher; // make entire class a friend public:

// same public members as before...

protected:

int semesterHours; // hours earned toward graduation float gpa;

};

Now, any member function of Teacher has access to the protected members of Student. Declaring one class a friend of the other inseparably binds the two classes together.