Download presentation
Presentation is loading. Please wait.
Published byAlfred Beasley Modified over 9 years ago
1
Inheritance – Derived Classes
2
Employee Inheritance Hierarchy Employee HourlyEmp SalariedEmp derived classes base class
3
Derived Classes Derived classes are used to create a class hierarchy. The superclass is called the base class. The subclass is called the derived class. Friendship is not inherited.
4
Specifying Inheritance In the class declaration, we follow class name with :superclass or :private superclass or :public superclass
5
Employee Inheritance Example class Employee { public: Employee( ); Employee(int emp_id, char *emp_name); Employee(const Employee &e); ~Employee( ); float calculate_pay( ); void set_tax_rate(float new_rate); void print( ); protected: float gross_pay; private: int id; char *name; float tax_rate; };
6
Employee Inheritance Example (Continued) class HourlyEmp : public Employee { public: HourlyEmp( ); HourlyEmp(int emp_id, char *emp_name); HourlyEmp(int emp_id, char *emp_name, float rate); HourlyEmp(const HourlyEmp &h); ~HourlyEmp( ); float calculate_pay( ); void set_hours(float worked); void set_pay_rate(float rate); void print( ); private: float hours_worked; float pay_rate; };
7
Member Visibility Class members are divided into three categories of accessibility: private memberCan be accessed only by the member functions and friends of its class protected memberBehaves as a public member to a derived class; it behaves as a private member to the rest of the program. public memberIs accessible from anywhere within a program.
8
Inheritance and Visibility Private inheritance changes the visibility of the base class members inherited by the derived class: private memberremains private in the derived class and is not accessible by the derived class methods protected memberbecomes private in the derived class public memberbecomes private in the derived class When public inheritance is used, the visibility of the base class members is not changed in the derived class
9
Storage Layout for Class Instances base class data derived class data
10
Visibility between Objects of the Same Class What can an object access within ITSELF and other objects of the SAME CLASS? [What part of Y can Z access?] A B B Y, Z; Base class parts (A part of Y) public protected private Derived class parts (B part of Y) public protected private Public inheritance Private inheritance YYnYYn YYYYYY YYnYYn YYYYYY
11
Visibility between Base and Derived Class Object What parts of an object can be accessed by another object of a DERIVED class? [What part of Y can be accessed by Z?] A B B Z; A Y; Base class parts (A part of Y) public protected private There is no B part of Y ! Public inheritance Private inheritance YYnYYn YnnYnn
12
External Visibility A B B Z; Base class parts (A part of Y) public protected private Derived class parts (B part of Y) public protected private Public inheritance Private inheritance YnnYnn YnnYnn nnnnnn YnnYnn What parts of an object can be accessed from OUTSIDE its inheritance hierarchy? [What part of Z can be accessed from main?]
13
Visibility of Members Example class A { public: int a1; void fa( ) { a1 = a2 = a3 = 0; } protected: int a2; private: int a3; }; main( ) { A x; x.a1 = 1; x.a2 = 1; main( ) cannot access A::a2: protected member x.a3 = 1; main( ) cannot access A::a3: private member }
14
Visibility of Members Example (Continued) class B : public A { public: int b1; void fb( ); protected: int b2; private: int b3; }; void B::fb( ) { b1 = b2 = b3 = 0; a1 = 1; a2 = 2; a3 = 3; B::fb() cannot access A::a3: private member }
15
Visibility of Members Example (Continued) main( ) { B y; y.a1 = 2; y.fa( ); y.a2 = 2; main( ) cannot access A::a2: protected member y.a3 = 2; main( ) cannot access A::a3: private member y.b1 = 2; y.b2 = 2; main( ) cannot access B::b2: protected member y.b3 = 2; main( ) cannot access B::b3: private member }
16
Visibility of Member Example (Continued) class C : private A { public: int c1; void fc( ); protected: int c2; private: int c3; }; void C::fc( ) { c1 = c2 = c3 = 0; a1 = 1; a2 = 2; a3 = 3; C::fc() cannot access A::a3: private member }
17
Visibility of Members Example (Continued) The following statements cause the indicated compiler errors: main( ) { C z; z.a1 = 3;//z.fa(); would be similar main( ) cannot access a1: A is a private base class z.a2 = 3; main() cannot access A::a2: protected member z.a3 = 3; main() cannot access A::a3: private member z.c1 = 3; z.c2 = 3; main() cannot access C::c2: protected member z.c3 = 3; main() cannot access C::c3: private member }
18
Summary of Access Rules for C++ C++ provides function and data protection through a combination of the following: public, private, and protected class members inheritance friendship
19
Invoking Parent Class Constructors In the constructor for a derived class, its parent’s constructor may be passed data by putting : BaseClassName (arguments) after the function header. For example, SalariedEmp (int id, char *name) : Employee(id, name) { } This allows the base class part of the object to be initialized at object construction. The parent’s constructor is always invoked before the body of the derived class constructor
20
Employee Constructor Examples Employee::Employee( ) : id(0), tax_rate(0) { name = strdup(“”); gross_pay = 0; } Employee::Employee (int emp_id, char *emp_name) { id = emp_id; name = strdup(emp_name); gross_pay = tax_rate = 0; } Employee::Employee (const Employee& e) { id = e.id; name = strdup(e.name); gross_pay = e.gross_pay; tax_rate = e.tax_rate; }
21
Employee Constructor Examples (Continued) HourlyEmp::HourlyEmp( ) { hours_worked = pay_rate = 0; } HourlyEmp::HourlyEmp(int emp_id, char *emp_name) : Employee(emp_id, emp_name) { hours_worked = pay_rate = 0; } HourlyEmp::HourlyEmp(int emp_id, char *emp_name, float rate) : Employee(emp_id, emp_name), pay_rate(rate), hours_worked(0) { } HourlyEmp::HourlyEmp(const HourlyEmp& h) : Employee(h) { hours_worked = h.hours_worked; pay_rate = h.pay_rate; }
22
Inherited Functions Member functions inherited from a public base class can be sent to instances of a derived class. An instance of a derived class can be passed as a parameter declared to be an instance of a public base class from which it is derived. A reference to a derived class can be passed as a parameter declared to be a reference to an instance of a public base class from which it is derived. A pointer to a derived class can be passed as a parameter declared to point to an instance of a public base class from which it is derived.
23
Inherited Functions (Continued) #include void test_function(Employee); main( ) { Employee e1(101, “Chris”), e2; HourlyEmp h1(102, “Kerry”), h2(103, “Lee”, 25.00); h2.set_hours(41.0); h2.set_tax_rate(0.18);// method inherited from Employee cout << “Pay = “ << h2.calculate_pay() << endl; test_function(e1); test_function(e2); } void test_function(Employee x) { x.print( ); cout << endl; }
24
Pointers to Class Instances A pointer to a base type is allowed to point to an instance of a class derived from it. This is not true if private inheritance was specified between the base and derived classes. Reference to a base class may also be assigned an instance of a class derived from it To allow a pointer to a derived class to point to an instance of its superclass, it must be explicitly converted with an appropriate constructor or type conversion operator.
25
Pointers to Class Instances (Continued) main( ) { Employee e1(101, “Chris”), e2; HourlyEmp h1(102, “Kerry”), h2(103, “Lee”, 25.00); Employee *eptr; HourlyEmp *hptr; eptr = &e1; hptr = &h2; eptr = &h1;// base class ptr points to derived class object // hptr = &e2;is not allowed // hptr = eptr;is not allowed eptr->print( );// use the pointer to invoke Employee::print hptr->print( );// invoke HourlyEmp::print hptr = (HourlyEmp *) eptr;// ok, but Dangerous! }
26
Classes That Allocate Storage
27
Storage Allocation - New This statement allocates storage for one object of type int. int *ptr = new int; This statement allocates storage for an array of ten objects of type int. int *ptr = new int[10]; This statement allocates storage for one object of type Myclass. After storage is allocated, the value 1024 is passed to the constructor and the storage is initialized. Myclass *ptr = new Myclass(1024);
28
Storage Allocation – New (Continued) new is a unary operator that takes a type as its operand and returns a pointer to free storage sufficient to hold an instance of that type. Vectors of objects may be allocated by using an array specifier in the operand of new. When new fails, it calls the function pointed to by the pointer _new_handler. If no such pointer is found, it returns 0. The pointer can be explicitly set, or the function set_new_hander can be called. new can be overloaded.
29
set_new_handler #include void noSpace( ) { cerr << “New Failed” << endl; exit(1); } main( ) { set_new_handler(noSpace); … }
30
Polygon Class Description Polygons are geometric figures with one or more sides. They have the following methods: A constructor that takes the number of sides and allocates storage for them. A void constructor that sets the number of sides to 0. A method to assign the length of the side of a polygon. A method to compute the perimeter of a polygon. A method to print the polygon. A method to compute the area of a polygon.
31
Polygon Class class Polygon// implements geometric shapes of 1 or more sides. {// uses ints to represent the lengths of the sides. public: Polygon( ); Polygon(int n_sides); void assignSide(int which_side, int len); int perimeter( ); void print( ); int area( ); protected: int *sides; private: int num_sides; };
32
Polygon Class (Continued) Polygon::Polygon(int n_sides) { num_sides = n_sides; sides = new int [num_sides]; for(int i = 0; i < num_sides; i++) assignSide(i,0); } Polygon::Polygon() { num_sides = 0; sides = NULL; }
33
Polygon Class (Continued) void Polygon::assignSide(int which_side, int len) { if(which_side < num_sides) sides[which_side] = len; else cerr << “assignSide: value out of range” << endl; } int Polygon::perimeter( ) { int sum = 0; for (int i = 0; i < num_sides; i++) sum += sides[i]; return sum; }
34
Polygon Class (Continued) int Polygon::area( ) { cerr << “Area undefined for generic polygon” << endl; return 0; } void Polygon::print( ) { cout << “A polygon with sides : “ << endl << “\t”; for(int i = 0; i < num_sides; i++) cout << “ “ << sides [i]; }
35
Using the Polygon Class Polygon triangle(3); main() { int side; for (int i = 0; i < 3; i++) { cin >> side; triangle.assignSide(i, side); } cout << triangle.perimeter( ); }
36
Storage Allocation - Delete delete is a unary operator that is applied to a pointer returned by new. It explicitly deallocates the storage pointed to by the pointer. For arrays of user-defined objects, use the following form: delete [ ] pointer; This ensures that the destructor is called for each element of the array. The compiler cannot distinguish a pointer to a vector from a pointer to a single object. delete can be overloaded
37
Polygon Class Destructor Polygon::~Polygon( ) { delete sides; }
38
Memberwise Assignment Polygons Polygon pentagon(5), triangle(3); Polygon aShape; aShape = triangle; 5 5 5 pentagon triangle aShape
39
Overloading = Polygon& Polygon::operator = (Polygon& p) { if(this != &p) { int *new_sides = new int[p.num_sides]; for(int i = 0; i < p.num_sides; i++) new_sides[i] = p.sides[i]; delete sides; sides = new_sides; num_sides = p.num_sides; } return (*this); }
40
Assignment versus Initialization Assignment and initialization are not the same. A user-defined assignment operator is not applied to an uninitialized object. Initialization (the copy constructor) is used when class instances are initialized in declarations, for passing instances as function arguments, and for returning instances from functions.
41
The Copy Constructor Polygon::Polygon(const Polygon& p) { num_sides = p.num_sides; sides = new int [num_sides]; for (int i = 0; i < num_sides; i++) sides[i] = p.sides[i]; }
42
Example of Constructor Invocation Polygon test(Polygon p)// passing a to test: copy constructor { return p;// return Polygon from test: copy constructor } main() { Polygon a(5);// 1-parameter constructor Polygon b = Polygon(3);// 1-parameter constructor (Polygon b(3)) Polygon c = a;// copy constructor Polygon d;// void constructor d = test(a);// assign result of test to d: assignment operator // destruct function argument: destructor // destruct temporary function result: destructor }// destruct d, c, b, a : destructor
43
Classes Allocating Storage When a class dynamically allocates storage, each of the following is necessary in the class: regular constructor(s) destructor overloaded assignment operator copy constructor
44
Default Memberwise Copy If class does not provide an overloaded assignment operator or copy constructor, when assignment or copying of instances is done, each base class and member class object in it has its assignment operator or copy constructor invoked, if it exists memberwise copy applied otherwise
45
Default Memberwise Copy (Continued) If a class does provide an overloaded assignment operator or copy constructor, it is invoked when assignment or copying of instances is done. It is the responsibility of the class operators to invoke the base class or member class operators, or both, as necessary. If both a derived class and a base class define assignment operators and a derived class object is assigned to a base class object, the type of the left- hand operand determines the assignment operator used.
46
Virtual Functions
47
Polygon Class class Polygon// implements geometric shapes of 1 or more sides. {// uses ints to represent the lengths of the sides. public: Polygon( ); Polygon(int n_sides); void assignSide(int which_side, int len); int perimeter( ); void print( ); int area( ); protected: int *sides; private: int num_sides; };
48
A Polygon Hierarchy Polygon TriangleRectangle Square
49
Using the Polygon Classes Polygon p1(5); Triangle t1, t2(10, 10, 10); Rectangle r1, r2(10, 20); Square s1, s2(10); p1.assignSide(0, 99); cout << t2.perimeter() << endl; t2.print(); cout << endl; cout << r2.area() << endl; r2.print(); cout << endl; cout << s2.area() << endl; s2.print(); cout << endl;
50
Accessing Polygons through Pointers Polygon *p[50]; Triangle t1, t2(10, 10, 10); Rectangle r1, r2(10, 20); Square s1, s2(10); p[0] = &t1; p[1] = &r2; p[2] = &s2; … cout area() << endl; p[i]->print();
51
Accessing Polygons through Pointers (Continued) Polygon TriangleRectangle Square The code for print() and area() is found in this class
52
Virtual Functions If we change the declaration of the function area in Polygon to virtual int area( ); And the declaration of function print in Polygon, to virtual void print( ); Then print and area are dynamically bound to the code, appropriate to the object to which they are sent.
53
Virtual Function (Continued) Polygon TriangleRectangle Square The code for p[1]->print( ), and p[1]->area( ), is found in this class The code for p[0]->print( ), and p[0]->area( ), is found in this class The code for p[2]->print( ), and p[2]->area( ), is found in this class
54
Virtual Function (Continued) The keyword virtual is specified once for the inheritance hierarchy by placing it in the root of the tree or subtree. It is used to dynamically bind a member function to the appropriate code, based on the type of the receiver. The derived classes can redefine the virtual function or inherit it. They can also define additional virtual functions. The access level (public, private, or protected) is specified by the type through which it is invoked.
55
Pure Virtual Functions In a base class, the virtual function declaration can be specified as follows: virtual retType name(arguments) = 0; This function is called a pure virtual function. The class declaring it is called an abstract class. It is illegal to create instances of classes containing one or more pure virtual function declarations. A pure virtual function that is not redefined in a derived class will be inherited as a pure virtual function, and the derived class will become an abstract class.
56
Virtual Destructors Given pointers to a base class (which may point to instances of the derived classes), if we delete them, we invoke the destructor for the base class. To overcome this, we use virtual destructors. To declare a destructor as virtual, precede its declaration with the keyword virtual, in the base class. Even though destructors in a derived class don’t have the same name as in the base class, they can still be declared virtual.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.