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

Chapter 19: Static Members: Can Fabric Softener Help? 255

to evaluate the expression. This is true even if nextStudent() should do other things, such as wash windows or shine your shoes. None of those things will be done. Although the example is obscure, it does happen. That’s what you get for trying to cram too much stuff into one expression.

Uses for static data members

Static data members have umpteen uses, but let me touch on a few here. First, you can use static members to keep count of the number of objects floating about. In the Student class, for example, the count is initialized to zero, the constructor increments it, and the destructor decrements it. At any given instant, the static member contains the count of the number of existing Student objects. Remember, however, that this count reflects the number of Student objects (including any temporaries) and not necessarily the number of students.

A closely related use for a static member is as a flag to indicate whether a particular action has occurred. For example, a class Radio may need to ini­ tialize hardware before sending the first tune command but not before subse­ quent tunes. A flag indicating that this is the first tune is just the ticket. This includes flagging when an error has occurred.

Another common use is to provide space for the pointer to the first member of a list — the so-called head pointer (see Chapter 14 if this doesn’t sound familiar). Static members can allocate bits of common data that all objects in all functions share (overuse of this common memory is a really bad idea because doing so makes tracking errors difficult).

Declaring Static Member Functions

Member functions can be declared static as well. Static member functions are useful when you want to associate an action to a class but you don’t need to associate that action with a particular object. For example, the member func­ tion Duck::fly() is associated with a particular duck, whereas the rather more drastic member function Duck::goExtinct() is not.

Like static data members, static member functions are associated with a class and not with a particular object of that class. This means that, like a ref­ erence to a static data member, a reference to a static member function does not require an object. If an object is present, only its type is used.

Thus, both calls to the static member function number() in the following example are legal. This brings us to our first static program — I mean our first program using static members — CallStaticMember:

256 Part III: Introduction to Classes

//

// CallStaticMember - demonstrate two ways to call a static // member function

//

#include <cstdio> #include <cstdlib> #include <iostream> using namespace std;

class Student

{

public:

Student(char* pN = “no name”)

{

pName = new char[strlen(pN) + 1]; if (pName)

{

strcpy(pName, pN);

}

noOfStudents++;

}

~Student() { noOfStudents--; }

static int number() { return noOfStudents; }

// ...other stuff the same...

protected: char* pName;

static int noOfStudents;

};

int Student::noOfStudents = 0;

int main(int argcs, char* pArgs[])

{

Student s1(“Chester”); Student s2(“Scooter”);

cout << “Number of students is “

<<s1.number() << endl; cout << “Number of students is “

<<Student::number() << endl;

//wait until user is ready before terminating program

//to allow the user to see the program results system(“PAUSE”);

return 0;

}

Notice how the static member function can access the static data member. On the other hand, a static member function is not directly associated with an object, so it doesn’t have default access to non-static members. Thus, the following would not be legal:

Chapter 19: Static Members: Can Fabric Softener Help? 257

class Student

{

public:

// the following is not legal static char* sName()

{

return pName;

// which pName? there’s no object

}

// ...other stuff the same...

protected: char* pName;

static int noOfStudents;

};

That’s not to say that static member functions have no access to non-static data members. Consider the following useful function findName() that finds a specific object in a linked list (see Chapter 14 for an explanation of how linked lists work). The majority of the code necessary to make the linked list work is left as an exercise for the reader. Don’t you just hate that phrase? But, seriously, the linked list code is already in Chapter 14:

class Student

{

public:

Student(char *pName)

{

//...construct the object and add it to a

//list of Student objects...

}

// findName - return student w/specified name static Student *findName(char *pName)

{

//...starting from the first object in the list

//which is pointed at by pHead link through

//the list using pNext until the correct

//object is found...

}

protected:

static Student *pHead; Student *pNext;

char* pName;

};

Student* Student::pHead = 0;

The function findName() has access to pHead because all objects share it. Being a member of class Student, findName() also has access to pNext.

258 Part III: Introduction to Classes

This access allows the function to navigate through the list until the matching object is found. The following shows how such static member functions might be used:

int main(int argcs, char* pArgs[])

{

Student s1(“Randy”); Student s2(“Jenny”);

Student s3(“Kinsey”);

Student *pS = Student::findName(“Jenny”); return 0;

}

What Is This About, Anyway?

It’s time to discuss the this keyword, just for grins. this is a pointer to the current object within a member function. It’s used when no other object name is specified. In a normal member function, this is the implied first argument to the function, as illustrated here:

class SC

{

public:

void nFn(int a); // like SC::nFn(SC *this, int a) static void sFn(int a); // like SC::sFn(int a)

};

void fn(SC& s)

{

s.nFn(10); // -converts to-> SC::nFn(&s, 10); s.sFn(10); // -converts to-> SC::sFn(10);

}

That is, the function nFn() is interpreted almost as though it were declared void SC::nFn(SC *this, int a). The call to nFn() is converted by the compiler as shown, with the address of s passed as the first argument. (You can’t actually write the call this way; this is only what the compiler is doing.)

References to other non-static members within SC::nFn() automatically use the this argument as the pointer to the current object. When SC::sFn() was called, no object address was passed. Thus, it has no this pointer to use when referencing non-static functions, which is why I say that a static member function is not associated with any current object.

Part IV

Inheritance

In this part . . .

In the discussions of object-oriented philosophy in Part III, two main features of real-world solutions

are seemingly not shared by functional programming solutions.

The first is the capability of treating objects separately.

I present the example of using a microwave oven to whip up a snack. The microwave oven provides an interface (the front panel) that I use to control the oven, without worrying about its internal workings. This is true even if I know all about how the darn thing works (which I don’t).

A second aspect of real-world solutions is the capability of categorizing like objects — recognizing and exploiting their similarities. If my recipe calls for an oven of any type, I should be okay because a microwave is an oven.

I already presented the mechanism that C++ uses to imple­ ment the first feature, the class. To support the second aspect of object-oriented programming, C++ uses a con­ cept known as inheritance, which extends classes.

Inheritance is the central topic of this part and the central message of the BUDGET3 program on the enclosed CD-ROM.

Chapter 20

Inheriting a Class

In This Chapter

Defining inheritance

Inheriting a base class

Constructing the base class

Exploring meaningful relationships: The IS_A versus the HAS_A relationship

This chapter discusses inheritance, the ability of one class to inherit capa­ bilities or properties from another class.

Inheritance is a common concept. I am a human (except when I first wake up in the morning). I inherit certain properties from the class Human, such as my ability to converse (more or less) intelligently and my dependence on air, water, and carbohydrate-based nourishment (a little too dependent on the latter, I’m afraid). These properties are not unique to humans. The class Human inherits the dependencies on air, water, and nourishment from the class Mammal, which inherited it from the class Animal.

The capability of passing down properties is a powerful one. It enables you to describe things in an economical way. For example, if my son asks, “What’s a duck?” I can say, “It’s a bird that goes quack.” Despite what you may think, that answer conveys a considerable amount of information. He knows what a bird is, and now he knows all those same things about a duck plus the duck’s additional property of “quackness.” (Refer to Chapter 12 for a further discus­ sion of this and other profound observations.)

Object-oriented (OO) languages express this inheritance relationship by allowing one class to inherit from another. Thus, OO languages can generate a model that’s closer to the real world (remember that real-world stuff!) than the model generated by languages that don’t support inheritance.

C++ allows one class to inherit another class as follows:

class Student

{

};