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

Chapter 20: Inheriting a Class 263

Another minor side effect has to do with software modification. Suppose you inherit from some existing class. Later, you find that the base class doesn’t do exactly what the subclass needs. Or, perhaps, the class has a bug. Modifying the base class might break any code that uses that base class. Creating and using a new subclass that overloads the incorrect feature solves your prob­ lem without causing someone else further problems.

How Does a Class Inherit?

Here’s the GraduateStudent example filled out into a program

InheritanceExample:

//

//InheritanceExample - demonstrate an inheritance

//

relationship in which the subclass

//

constructor passes argument information

//

to the constructor in the base class

//

 

#include <cstdio>

#include <cstdlib>

#include <iostream>

#include <strings.h>

using namespace std;

// Advisor - empty class

class Advisor {};

const int MAXNAMESIZE = 40;

class Student

{

public:

 

 

Student(char *pName = “no name”)

 

: average(0.0), semesterHours(0)

 

{

 

strncpy(name, pName, MAXNAMESIZE);

 

name[MAXNAMESIZE - 1] = ‘\0’;

 

cout << “constructing student “

 

<< name

 

<< endl;

 

}

 

void addCourse(int hours, float grade)

 

{

 

cout << “adding grade to “ << name << endl;

 

average = (semesterHours * average + grade);

 

semesterHours += hours;

 

average = average / semesterHours;

 

}

264 Part IV: Inheritance

int hours( ) { return semesterHours;} float gpa( ) { return average;}

protected:

char name[MAXNAMESIZE]; int semesterHours; float average;

};

class GraduateStudent : public Student

{

public:

GraduateStudent(char *pName, Advisor& adv, float qG = 0.0)

: Student(pName), advisor(adv), qualifierGrade(qG)

{

cout << “constructing graduate student “

<<pName

<<endl;

}

float qualifier( ) { return qualifierGrade; }

protected: Advisor advisor;

float qualifierGrade;

};

int main(int nNumberofArgs, char* pszArgs[])

{

Advisor advisor;

//create two Student types Student llu(“Cy N Sense”);

GraduateStudent gs(“Matt Madox”, advisor, 1.5);

//now add a grade to their grade point average llu.addCourse(3, 2.5);

gs.addCourse(3, 3.0);

//display the graduate student’s qualifier grade cout << “Matt’s qualifier grade = “

<<gs.qualifier()

<<endl;

//wait until user is ready before terminating program

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

return 0;

}

This program demonstrates the creation and use of two objects, one of class Student and a second of GraduateStudent. The output of this program is as follows:

Chapter 20: Inheriting a Class 265

constructing student Cy N Sense constructing student Matt Madox constructing graduate student Matt Madox adding grade to Cy N Sense

adding grade to Matt Madox Matt’s qualifier grade = 1.5 Press any key to continue . . .

Using a subclass

The class Student has been defined in the conventional fashion. The class GraduateStudent is a bit different, however; the colon followed by the phrase public Student at the beginning of the class definition declares

GraduateStudent to be a subclass of Student.

The appearance of the keyword public implies that there is probably pro­ tected inheritance as well. All right, it’s true, but protected inheritance is beyond the scope of this book.

Programmers love inventing new terms or giving new meaning to existing terms. Heck, programmers even invent new terms and then give them a second meaning. Here is a set of equivalent expressions that describes the same relationship:

GraduateStudent is a subclass of Student.

Student is the base class or is the parent class of GraduateStudent.

GraduateStudent inherits from Student.

GraduateStudent extends Student.

As a subclass of Student, GraduateStudent inherits all of its members. For example, a GraduateStudent has a name even though that member is declared up in the base class. However, a subclass can add its own members, for example qualifierGrade. After all, gs quite literally IS_A Student plus a little bit more than a Student.

The main() function declares two objects, llu of type Student and gs of type GraduateStudent. It then proceeds to access the addCourse() member function for both types of students. main() then accesses the qualifier() function that is only a member of the subclass.

Constructing a subclass

Even though a subclass has access to the protected members of the base class and could initialize them, each subclass is responsible for initializing itself.

266 Part IV: Inheritance

Before control passes beyond the open brace of the constructor for GraduateStudent, control passes to the proper constructor of Student. If Student were based on another class, such as Person, the constructor for that class would be invoked before the Student constructor got control. Like a skyscraper, the object is constructed starting at the “base”-ment class and working its way up the class structure one story at a time.

Just as with member objects, you often need to be able to pass arguments to the base class constructor. The example program declares the subclass con­ structor as follows:

GraduateStudent(char *pName, Advisor& adv, float qG = 0.0) : Student(pName), advisor(adv), qualifierGrade(qG)

{

// whatever construction code goes here

}

Here the constructor for GraduateStudent invokes the Student construc­ tor, passing it the argument pName. C++ then initializes the members advisor and qualifierGrade before executing the statements within the constructor’s open and close braces.

The default constructor for the base class is executed if the subclass makes no explicit reference to a different constructor. Thus, in the following code snippet the Pig base class is constructed before any members of LittlePig, even though LittlePig makes no explicit reference to that constructor:

class Pig

{

public:

Pig() : pHouse(null) {}

protected: House* pHouse;

};

class LittlePig : public Pig

{

public:

LittlePig(float volStraw, int numSticks, int numBricks)

: straw(volStraw), sticks(numSticks), bricks(numBricks)

{}

protected: float straw; int sticks; int bricks;

};

Similarly, the copy constructor for a base class is invoked automatically.