1.03k likes | 1.17k Views
CHAPTER 6_1 INHERITANCE AND COMPOSITION. In this chapter, you will: Learn about inheritance Learn about derived and base classes Explore how to redefine the member functions of a base class Examine how the constructors of base and derived classes work
E N D
In this chapter, you will: • Learn about inheritance • Learn about derived and base classes • Explore how to redefine the member functions of a base class • Examine how the constructors of base and derived classes work • Learn how to construct the header file of a derived class • Explore three types of inheritance: public, protected, and private • Learn about composition • Become familiar with the three basic principles of object-oriented design
Inheritance and Composition The two common ways to relate two classes in a meaningful way are: 1. Inheritance (“is-a” relationship), and 2. Composition (“has-a” relationship).
INHERITANCE • Design a class, partTimeEmployee, to implement and process the characteristics of a part-time employee. • Every part-time employee has a name, pay rate, and number of hours worked. • Every part-time employee is a person. • Rather than design the class partTimeEmployee from scratch, we want to be able to extend the definition of the classpersonType by adding additional members (data and/or function). • We do not want to make the necessary changes directly to the classpersonType—that is, edit the classpersonType, and add and/or delete members. • We want to create the classpartTimeEmployee without making any physical changes to the classpersonType, by adding only the members that are necessary.
The new class that we create from existing classes is called the derived class and the existing classes are called the base classes. • Single inheritance- the derived class is derived from a single base class. • Multiple inheritance- the derived class is derived from more than one base class.
Inheritance can be viewed as a tree-like, or hierarchical, structure wherein a base class is shown with its derived classes.
class circle: public shape { . . . }; • The word public in the heading, called the member access specifier, specifies that all public members of the classshape are inherited as public members by the classcircle.
class circle: private shape { . . . }; • In this definition, the public members of shape become private members of the classcircle. • The previous definition of circle is equivalent to class circle: shape { . . . };
The general syntax of a derived class is class className: memberAccessSpecifier baseClassName { member list }; where memberAccessSpecifier is public, protected, or private. • When no memberAccessSpecifier is specified, it is assumed to be a private inheritance.
The following facts about the base and the derived classes should be kept in mind. 1. The private members of the base class are private to the base class; hence, the members of the derived class cannot directly access them. 2. The public members of a base class can be inherited either as public members or as private members by the derived class. 3. The derived class can include additional data and/or function members. 4. The derived class can redefine the public member functions of the base class. However, this redefinition applies only to the objects of the derived class, not to the objects of the base class. 5. All data members of the base class are also data members of the derived class. Similarly, the member functions of the base class (unless redefined) are also the member functions of the derived class.
Redefining Member Functions of the Base Class class baseClass { public: void print() const; private: int u; int v; char ch; }; void baseClass::print() const { cout<<"Base Class: u = "<<u<<", v = "<<v <<", ch = "<<ch<<endl; }
class derivedClass: public baseClass { public: void print() const; private: int first; double second; }; • The classderivedClass is derived from the classbaseClass and it is a public inheritance. • All public members of baseClass are inherited as public members of derivedClass. • The classderivedClass also overwrites the print function.
The classderivedClass has five data members: u, v, ch, first, and second. • To write the definition of the member function print of derivedClass, keep the following in mind: • The data members u, v, and ch are private members of the classbaseClass. • When writing the definition of the function print of derivedClass, we cannot reference u, v, and ch directly. • The data members u, v, and ch of the classbaseClass are accessible in derivedClass through the public members of baseClass.
void derivedClass::print() const { baseClass::print(); cout<<"Derived Class: first = "<<first <<", second = "<<second<<endl; cout<<"___________________________________" <<"________"<<endl; } baseClass baseObject; derivedClass derivedObject;
baseClass baseObject; derivedClass derivedObject;
baseObject.print(); derivedObject.print(); • In the first statement, the function print of the baseClass is executed • In the second statement, the function print associated with the classderivedClass is executed. • The output of the first statement is Base Class: u = 5, v = 6, ch = * The output of the second statement is Base Class: u = 12, v = 76, ch = & Derived Class: first = 32, second = 16.38
Constructors of Derived and Base Classes • A derived class can have its own private data members. • Member functions of the derived class cannot directly access the private members of the base class. • The constructors of the derived class can (directly) initialize only the private data members of the derived class. • When a derived class object is declared, it must also automatically execute one of the constructors of the base class. • The execution of a derived class’s constructor must trigger the execution of one of the base class’s constructors. • A call to the base class’s constructor is specified in the heading part of the derived class constructor’s definition.
class baseClass { public: void print(); //baseClass Line 1 baseClass(); //baseClass Line 2 baseClass(int x, int y); //baseClass Line 3 baseClass(int x, int y, char w); //baseClass Line 4 private: int u; int v; char ch; };
void baseClass::print() { cout<<"Base Class: u = "<<u<<", v = "<<v <<", ch = "<<ch<<endl; } //default constructor; baseClass Line 2 baseClass::baseClass() { u = 0; v = 0; ch = '*'; } //constructor; baseClass Line 3 baseClass::baseClass(int x, int y) { u = x; v = y; ch = '*'; }
//constructor; baseClass Line 4 baseClass::baseClass(int x, int y, char w) { u = x; v = y; ch = w; } class derivedClass: public baseClass { public: void print(); //derivedClass Line 1 derivedClass(); //derivedClass Line 2 derivedClass(int x, int y, int one, double two); //derivedClass Line3 derivedClass(int x, int y, char w, int one, double two); //derivedClass Line 4 private: int first; double second; };
void derivedClass::print() { baseClass::print(); cout<<"Derived Class: first = "<<first <<", second = "<<second<<endl; cout<<"__________________________________" <<"_________"<<endl; } derivedClass::derivedClass() //default constructor { first = 0; second = 0; } derivedClass::derivedClass(int x, int y, int one, double two) : baseClass(x,y) //derivedClass constructor Line 3 { first = one; second = two; }
//derivedClass; constructor Line 4 derivedClass::derivedClass(int x, int y, char w, int one, double two) :baseClass(x,y,w) { first = one; second = two; } #include <iostream> #include "baseClass.h" #include "derivedClass.h" using namespace std; int main() { baseClass baseObject1; baseClass baseObject2(5,6); baseClass baseObject3(4,8,'K'); derivedClass derivedObject1; derivedClass derivedObject2(12,13,45,8.5); derivedClass derivedObject3(21,23,'Y',76,64.58);
cout<<"Line 1: baseObject1: "; baseObject1.print(); //main Line 1 cout<<"Line 2: baseObject2: "; baseObject2.print(); //main Line 2 cout<<"Line 3: baseObject3: "; baseObject3.print(); //main Line 3 cout<<"Line 4: -*-*-*-*-*-*-*-*-*-*" <<"-*-*-*-*-*-*-*-*-*-*-*-"<<endl; //main Line 4 cout<<"Line 5: Derived Class Objects." <<endl; //main Line 5 cout<<endl; cout<<"Line 6: derivedObject1: "<<endl; derivedObject1.print(); //main Line 6 cout<<"Line 7: derivedObject2: "<<endl; derivedObject2.print(); //main Line 7 cout<<"Line 8: derivedObject3: "<<endl; derivedObject3.print(); //main Line 8 return 0; }
OUTPUT: Line 1: baseObject1: Base Class: u = 0, v = 0, ch = * Line 2: baseObject2: Base Class: u = 5, v = 6, ch = * Line 3: baseObject3: Base Class: u = 4, v = 8, ch = K Line 4: -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- Line 5: Derived Class Objects. Line 6: derivedObject1: Base Class: u = 0, v = 0, ch = * Derived Class: first = 0, second = 0 ___________________________________________ Line 7: derivedObject2: Base Class: u = 12, v = 13, ch = * Derived Class: first = 45, second = 8.5 ___________________________________________ Line 8: derivedObject3: Base Class: u = 21, v = 23, ch = Y Derived Class: first = 76, second = 64.58 ___________________________________________
Example 14-1 class partTimeEmployee: public personType { public: void print(); //Function to output the first name, last name, //and the wages in the form: //firstName lastName wages are $$$$.$$ double calculatePay(); void setNameRateHours(string first, string last, double rate, double hours); partTimeEmployee(string first, string last, double rate, double hours); partTimeEmployee(); private: double payRate; //store the pay rate double hoursWorked; //store the hours worked };
void partTimeEmployee::print() { personType::print(); //print the name of the employee cout<<" wages are : "<<calculatePay()<<endl; } double partTimeEmployee::calculatePay() { return (payRate * hoursWorked); } void partTimeEmployee::setNameRateHours (string first, string last, double rate, double hours) { personType::setName(first,last); payRate = rate; hoursWorked = hours; }
partTimeEmployee::partTimeEmployee(string first, string last, double rate, double hours) : personType(first, last) { payRate = rate; hoursWorked = hours; } //default constructor partTimeEmployee:: partTimeEmployee() { payRate = 0; hoursWorked = 0; }
Header File of a Derived Class //Header file ptEmployee.h #include "person.h" class partTimeEmployee: public personType { public: void print() const; double calculatePay(); void setNameRateHours(string, string, double, double); partTimeEmployee(string, string, double, double); partTimeEmployee(); //default constructor private: double payRate; double hoursWorked; };
Multiple Inclusions of a Header File //Header file test.h constint one = 1; constint two = 2; • Suppose that the header file testA.h includes the file test.h to make use of the identifiers one and two. //Header file testA.h #include "test.h" . . .
// Program headerTest.cpp #include "test.h" #include "testA.h" . . . • The preprocessor first includes the header file test.h and then the header file testA.h. • When the header file testA.h is included, because it contains the preprocessor directive #include"test.h", the header file test.h will be included twice in the program. • The second inclusion of the header file test.h will result in compile time errors, such as identifier one already declared. • To avoid multiple inclusion of a file in a program we use certain preprocessor commands in the header file.
//Header file test.h #ifndef H_test #define H_test constint one = 1; const int two = 2; #endif a. #ifndef H_test means “if not defined H_test” b. #define H_test means “define H_test” c. #endifmeans“end if” • H_test is a preprocessor identifier. • All header files are written using similar preprocessor commands.
The classios is the base class for all stream classes. • Classes istream and ostream are directly derived from the classios. • The classifstream is derived from the classistream, and the classofstream is derived from the classostream. • The classios contains formatting flags and member functions to access and/or modify the setting of these flags. • To identify the I/O status, the classios contains an integer status word. This integer status word provides a continuous update reporting the status of the stream. • The classesistream and ostream are responsible for providing the operations for the data transfer between memory and devices.
The classistream defines the extraction operator, >>, and functions such as get and ignore. • The classostream defines the insertion operator, <<, which is used by the object cout. • The classifstream is derived from the classistream to provide the file input operations. • The classofstream is derived from the classostream to provide the file output operations. • Objects of the type ifstream are used for file output; objects of the type ofstream are used for file output. • The header file fstream contains the definition of the classes ifstream and ofstream.
Protected Members of a Class • The private members of a class are private to the class and cannot be directly accessed outside the class. • The derived class cannot access private members of a class. • It is sometimes necessary for a derived class to access a private member of a base class. • If you make a private member become public, then anyone can access that member. • For a base class to give access to a private member to its derived class and still prevent its direct access outside the class, you must declare that member under the memberAccessSpecifier protected. • The accessibility of a protectedmember of a class is in between public and private. • A derived class can directly access the protected member of a base class.
Inheritance as public, protected, or private class B: memberAccessSpecifier A { . . . }; • memberAccessSpecifier is either public, protected, or private.
1. If memberAccessSpecifier is public, then a. The public members of A are public members of B. They can be directly accessed in classB. b. The protected members of A are protected members of B. They can be directly accessed by the member functions (and friend functions) of B. c. The private members of A are hidden in B. They can be accessed by the member functions (and friend functions) of B through the public or protected members of A. 2. If memberAccessSpecifier is protected, then a. The public members of A are protected members of B. They can be accessed by the member functions (and friend functions) of B. b. The protected members of A are protected members of B. They can be accessed by the member functions (and friend functions) of B. c. The private members of A are hidden in B. They can be accessed by the member functions (and friend functions) of B through the public or protected members of A.
3. If memberAccessSpecifier is private, then a. The public members of A are private members of B. They can be accessed by the member functions (and friend functions) of B. b. The protected members of A are private members of B. They can be accessed by the member functions (and friend functions) of B. c. The private members of A are hidden in B. They can be accessed by the member functions and (and friend functions) of B through the public or protected members of A.
Example 14-2: (Accessing protected members in the derived class.) class bClass { public: void setData(double); void setData(char, double); void print() const; bClass(char = '*', double = 0.0); protected: char bCh; private: double bX; };
void bClass::setData(double u) { bX = u; } void bClass::setData(char ch, double u) { bCh = ch; bX = u; } void bClass::print() const { cout<<"Base class: bCh = "<<bCh<<", bX = "<<bX<<endl; } bClass::bClass(char ch, double u) { bCh = ch; bX = u; }
class dClass: public bClass { public: void setData(char, double, int); void print() const; private: int dA; }; void dClass::setData(char ch, double v, int a) { bClass::setData(v); bCh = ch; //initialize bCh using the assignment //statement dA = a; }
void dClass::print() const { bClass::print(); cout<<"Derived class dA = "<<dA<<endl; } //Accessing protected members of a base class //in the derived class #include <iostream> #include "protectMembClass.h" #include "protectMembInDerivedCl.h" using namespace std; int main() { bClass bObject; //Line 1 dClass dObject; //Line 2
bObject.print(); //Line 3 cout<<endl; //Line 4 cout<<"*** Derived class object ***"<<endl; //Line 5 dObject.setData('&', 2.5, 7); //Line 6 dObject.print(); //Line 7 return 0; } Output Base class: bCh = *, bX = 0 *** Derived class object *** Base class: bCh = &, bX = 2.5 Derived class dA = 7
COMPOSITION • In composition one (or more) member(s) of a class is an object of another class type. • Composition is a “has-a” relation.
class dateType { public: void setDate(int month, int day, int year); void getDate(int& month, int& day, int& year); void printDate() const; dateType(int month, int day, int year); dateType(); private: int dMonth; //variable to store the month int dDay; //variable to store the day int dYear; //variable to store the year };