Understanding Inheritance Object-Oriented Programming Using C++ Second Edition 9.

Post on 21-Dec-2015

220 views 0 download

Transcript of Understanding Inheritance Object-Oriented Programming Using C++ Second Edition 9.

Understanding Inheritance

Object-Oriented Programming Using C++

Second Edition

9

Objectives

• In this chapter, you will learn:

• About inheritance and its benefits

• How to create a derived class

• About restrictions imposed with inheritance

• How to choose a class access specifier

• How to override and overload parent class functions within a child class

• How to use a constructor initialization list

9

Objectives

• In this chapter, you will learn:

• How to provide for a base class constructor within a derived class

• How to override the class access specifier

• How to use multiple inheritance

• About the special problems posed by multiple inheritance

• How to use virtual inheritance

9

Understanding Inheritance

• Objects used in computer programs also are easier to understand if you can place them within a hierarchy of inheritance

• Suppose you have written several programs with a class named Student

• The FirstYearStudent class inherits from the Student class, or is derived from it

• The Student class is called a parent class, base class, superclass, or ancestor; the FirstYearStudent class is called a child class, derived class, subclass, or descendant

• When you override a function, you substitute one version of the function for another

9

Understanding the Advantages Provided by Inheritance

• Inheritance is considered a basic building block of object-oriented programming

• Programs in which you derive new classes from existing classes offer several advantages:

– You save time because much of the code needed for your class is already written

– You save additional time because the existing code has already been tested—that is, you know it works correctly; it is reliable

9

Understanding the Advantages Provided by Inheritance

• Advantages of using derived classes:

– You save even more time because you already understand how the base class works, and you can concentrate on the complexity added as a result of your extensions to the class

– In a derived class, you can extend and revise a parent class without corrupting the existing parent class features

– If other classes have been derived from the parent class, the parent class is even more reliable—the more its code has been used, the more likely it is that logical errors have already been found and fixed

9

Creating a Derived Class

• The class, named Person, is shown in Figure 9-1• It contains three fields, and two member functions that set

and display the data field values

9

Creating a Derived Class

• To create a derived class, you include the following elements in the order listed:– Keyword class

– Derived class name

– Colon

– Class access specifier, either public, private, or protected

– Base class name

– Opening brace

– Class definition statements

– Closing brace

– Semicolon

9

Creating a Derived Class

• The Customer class shown in Figure 9-2 contains all the members of Person because it inherits them

9

The Customer Class

9

Creating a Derived Class9

Creating a Derived Class

• In the set of steps outlined on pages 317 to 319 of the textbook, you create two classes, Car and Convertible

• The Car class serves as a base class and includes features common to all cars

9

Creating a Derived Class

• You create the Convertible class and a demonstration program in the steps referred to on pages 319 and 320 of the textbook

9

Understanding Inheritance Restrictions

• Figure 9-8 shows a modified version of the Customer class outputBalDue() function, originally presented in Figure 9-3

• The improvement lies in the addition of the Customer ID number to the explanation of the output

• However, if you replace the original outputBalDue() function with the one shown in Figure 9-8, programs that use the function no longer run

• The error message states that idNum is inaccessible; that is, the Customer class function cannot use it

9

Understanding Inheritance Restrictions

• When a class serves as a base class to other classes, all of its members can be used within the child class functions, except for private members

• While having private members is a good idea, it often is inconvenient

• There are times when you want a child class object to be able to access private data members that it owns, but that originated with the parent

• Fortunately, C++ provides an alternative to private and public specifiers

9

Understanding Inheritance Restrictions

• The protected specifier allows members to be used by class member functions and by derived classes, but not by other parts of a program

9

Understanding Inheritance Restrictions

• A child class function cannot use its parent class’s constructor

• The following are never inherited:

– Constructor functions

– Destructor functions

– Friend functions

– Static data members

– Static member functions

– Overloaded new operators

– Overloaded = operators

9

Choosing the Class Access Specifier

• C++ programmers usually use the public access specifier for inheritance

• If a derived class uses the public access specifier, then the following statements are true:

– Base class members that are public remain public in the derived class

– Base class members that are protected remain protected in the derived class

– Base class members that are private are inaccessible in the derived class

9

Choosing the Class Access Specifier

• If a derived class uses the protected access

specifier, then the following statements are true:

– Base class members that are public become protected

in the derived class

– Base class members that are protected remain

protected in the derived class

– Base class members that are private are inaccessible in

the derived class

9

Choosing the Class Access Specifier

• If a derived class uses the private access

specifier, then the following statements are true:

– Base class members that are public become private in

the derived class

– Base class members that are protected become private

in the derived class

– Base class members that are private are inaccessible in

the derived class

9

Choosing the Class Access Specifier

• Figure 9-10 shows a class named DemoBasePerson that contains three data members

• For illustration, one field is private, another is protected, and the third field is public

• The setPerson() and showPerson() functions also are public

9

Choosing the Class Access Specifier

9

Choosing the Class Access Specifier

• The two highlighted and commented cout statements in Figure 9-11 are not correct

• If you remove the comment designation from either of these statements, the program does not compile

• The DemoBasePerson class fields age and salary are not accessible from within the main() program because they are not public

• The showIntrovert() function in Figure 9-13 could call the showPerson() function, which is public in DemoBasePerson and private in Introvert, and the showPerson() function could then access salary

9

Choosing the Class Access Specifier

• A main() program that instantiates an Introvert object cannot access any of the four data items directly; all four fields are private to the Introvert class

9

Choosing the Class Access Specifier

9

Choosing the Class Access Specifier

• To summarize the use of three class access specifiers with class data members:

– If a class has private data members, they can be used only by member functions of that class

– If a class has protected data members, they can be used by member functions of that class and by member functions of derived classes

– If a class has public data members, they can be used by member functions of that class, by member functions of derived classes, and by any other functions’ including the main() function of a program

9

Choosing the Class Access Specifier

• With one generation of inheritance, there are nine possible combinations, as shown in Table 9-1

• Remember the following:

– Private data can be accessed only by a class’s member functions (or friend functions), and not by any functions in derived classes

– If a class serves as a base class, most often its data members are protected, and its member functions are public

– The access spcifier in derived classes is most often public, so that the derived class can refer to all nonprivate data and functions of the base class

– When a class is derived from another derived class, the newly derived class never has any more liberal access to a base class member than does its immediate predecessor

9

Summary of Child Class Member Access Rules

9

Overriding and Overloading Parent Class Functions

• When a new class is derived from an existing class, the derived class has access to nonprivate member functions in the base class

• The new class also can have its own member functions

• Those functions can have names that are identical to the function names in the base class

• Any child class function with the same name and argument list as the parent overrides the parent function; any child class function with the same name as the parent, yet with an argument that differs from the parent’s, overloads the parent function

9

Overriding and Overloading Parent Class Functions

9

Overriding and Overloading Parent Class Functions

• The Employee setFields() function receives values for fields that are defined in the parent Person class, as well as for fields defined within the Employee class

• Employee::setFields() could directly assign values to idNum, lastName, and firstName, as shown in Figure 9-18

• The highlighted lines of code in Figure 9-18 are identical to lines of code in the parent class version of setFields(), so you can rewrite the Employee class setFields() function to call Person’s setFields() function

9

Overriding and Overloading Parent Class Functions

9

Overriding and Overloading Parent Class Functions

• In the highlighted statement in the setFields() function in Figure 9-19, the values for num, last, and first are passed to the parent class function, where they are assigned to the appropriate fields

• It is important to use the parent class name (Person) and the scope resolution operator

9

Overriding and Overloading Parent Class Functions

• The output in Figure 9-21 shows that even though you set fields for a Person and an Employee by using separate functions that require separate argument lists, you use the same outputData() function that exists within the parent class for both a Person and an Employee

9

Overriding and Overloading Parent Class Functions

9

Overriding and Overloading Parent Class Functions

• A derived class object can be assigned to a base class object, as in aPerson = worker;

• The assignment causes each data member to be copied from worker to aPerson, and leaves off any data for which the base class doesn’t have members

• The reverse assignment cannot take place without writing a specialized function

• When any class member function is called, the steps shown on page 333 of the textbook take place

9

Overriding and Overloading Parent Class Functions

• In the set of steps outlined on pages 333 and 334 of the textbook, you create a RaceCar class as a child of the Car class you created earlier

• A RaceCar has all the attributes of a Car, but its maximum allowed speed is higher

• Overriding a base class member function with a derived member function demonstrates the concept of polymorphism

9

Using Constructor Initialization Lists

• Many classes use a constructor function to provide initial values for fields when a class object is created; that is, many functions simply contain a series of assignment statements

• As an alternative to the separate prototype and implementation of the constructor shown in Figure 9-25, you can implement the constructor within the declaration section for the class as an inline function

9

The Item Class

9

Using Constructor Initialization Lists

• As another alternative, you can replace the assignment statements within a constructor body for Item with a constructor initialization list

• A constructor initialization list provides values for class fields in the same statement that contains the constructor definition

9

Using Constructor Initialization Lists

• The constructor initialization list shown in

Figure 9-27 initializes itemNum with the value

of n and itemPrice with the value of p

9

Understanding the Difference Between Assignment

and Initialization

• The difference between assignment and initialization is often very subtle, and programmers sometimes mingle the two terms rather casually

• When you declare a simple scalar variable and give it a value, you can declare and assign in two separate statements, for example:int z;

z = 100;

• Alternatively, you can initialize a variable, declaring it and assigning it a value within a single statement, for example:int z = 100;

OR

int z(100);

9

Understanding the Difference Between Assignment

and Initialization

• There are at least four reasons to understand the use of constructor initialization lists:– Many C++ programmers prefer this method, so it is used

in many programs– Technically, a constructor should initialize rather than

assign values– Reference variables and constant class members

cannot be assigned values; they must be initialized– When you create a derived class and instantiate an

object, a parent class object must be constructed first. You add a constructor initialization list to a derived class constructor to construct the parent class.

9

Providing for Base Class Construction

• When you instantiate an object in a C++ program, you automatically call its constructor function

• This pattern holds true whether you write a custom constructor or use a default constructor

• When you instantiate a derived class object, a constructor for its base class is called first, followed by the derived class constructor

• This format is followed even if the base and derived classes both have only default constructors

9

Providing for Base Class Construction

9

Providing for Base Class Construction

• If PetStoreAnimal were a simple base class, the PetStoreAnimal class constructor would require just an integer argument that would be assigned to the petAge field

• However, because PetStoreAnimal is derived from PetStoreItem, a PetStoreAnimal object is constructed, and the PetStoreItem class constructor also will be called

• The prototype for the PetStoreAnimal class constructor must provide values for all the arguments it needs as well as all the arguments its parent needs

9

The PetStoreAnimal Class

9

Providing for Base Class Construction

• Figure 9-31 shows one more option for coding the PetStoreAnimal class

• In this example, the constructor initialization list initializes both PetStoreItem and petAge

9

Overriding Inherited Access

• Nine inheritance access specifier combinations are possible: base class members that are private, protected, or public can be inherited with private, protected, or public access

• In addition, you can override the class access specifier for any specific class members

9

The DemoBasePerson Class

9

Overriding Inherited Access

• If a derived class, SomewhatShy, uses the protected access specifier when inheriting from DemoBasePerson, then the following statements hold true:

– The field named salary, which is private in DemoBasePerson, is inaccessible in the derived class

– The field named age, which is protected in the base class, remains protected in the derived class

– The field named initial, which is public in the base class, becomes protected in the derived class

– The function setPerson() and showPerson(), which are public in DemoBasePerson, become protected in the derived class

9

Overriding Inherited Access

• For the showPerson() function to become public within SomewhatShy, the highlighted statement in Figure 9-33 must appear in the public section of the SomewhatShy class

• Additionally, the DemoBasePerson class name and scope resolution operator must appear before the showPerson() function name

• Finally, and most oddly, no parentheses appear after the showPerson() function name within the child class

9

Overriding Inherited Access

• However, you can override the inherited access to make an individual member’s access more conservative

• For most C++ classes, data is private or protected, and most functions are public

9

Using Multiple Inheritance

• A child class also can derive from more than one base class; this type of inheritance is called multiple inheritance

9

The Employee Class

9

Using Multiple Inheritance

• The new Patent class, shown in Figure 9-37, inherits from both Product and Employee

• The Patent class includes all members of each of its parents’ classes

• Figure 9-38 shows a main() function that uses a Patent object, and Figure 9-39 shows the output

• Five arguments are passed to the Patent class setData() function

9

The Patent Class

9

Using Multiple Inheritance9

Using Multiple Inheritance

• In the steps on pages 345 to 348 of the textbook, you create two classes

• The Investment class holds data about Investment objects, such as initial value and profit figures

• The House class holds data about House objects, such as number of bedrooms and square footage

9

Disadvantages of Using Multiple Inheritance

• Multiple inheritance is never required to solve a programming problem; the same results always can be achieved through single inheritance

• You already have encountered one problem with multiple inheritance: if two parent classes contain members with the same name, then the awkward syntax of using the scope resolution operator is required when using those members

• In the set of steps referred to on pages 349 and 350 of the textbook, you alter the House and Investment classes you created earlier so they each contain a constructor that requires arguments

9

Using Virtual Base Classes

• You already know that a base class may have many descendants through single inheritance

• A college might use a Person base class, for example, and create child classes Student, Employee, and Alumnus

• You also know that a class may inherit from two other classes through multiple inheritance

9

Using Virtual Base Classes

• The class definition for StudentEmployee would begin as follows:

class StudentEmployee: public Student, public Employee

• The word virtual indicates that the base class should be used only once

• The headers of the classes become:

class Student : virtual public Person

AND

class Employee : virtual public Person

9

Summary

• Inheritance allows you to create classes that derive most of their attributes from existing classes

• Programs in which you create classes that are derived from existing classes offer several advantages: you save time because much of the code needed for your class is already written and tested

• To create a derived class, you include the keyword class, the derived class name, a colon, a class access specifier, and the base class name in the class header; as with other classes, definition statements within a pair of curly braces follow

9

Summary

• When a class serves as a base class to others, all of its members can be used within the child class functions, except for any private members

• When you define a derived class, you can insert one of the three class access specifiers (public, private, or protected) just prior to the base class name

• You can override parent class functions within a child class

• As an alternative to separate prototypes and implementation of a constructor, you can use a constructor initialization list

9

Summary

• When you declare a variable without an initial value, it holds garbage until you make an assignment

• If a base class does not contain a default constructor, then you must provide a constructor for use by the derived class

• You can override the class access specifier when it does not suit your needs for some of the members of the class

9

Summary

• Using multiple inheritance, a child class can derive from more than one base class

• Multiple inheritance poses special problems, and some programmers are opposed to its use

• When a base class is parent to two or more classes that in turn are co-parents to another generation, you risk duplicate inheritance

• To remedy this situation, you use the keyword virtual when you define each of the child classes; this indicates that the base class should be used only once

9