Object Oriented Programming CS250

Similar documents
CS 162, Lecture 25: Exam II Review. 30 May 2018

OBJECT ORIENTED PROGRAMMING USING C++ CSCI Object Oriented Analysis and Design By Manali Torpe

What is Polymorphism? Quotes from Deitel & Deitel s. Why polymorphism? How? How? Polymorphism Part 1

Polymorphism Part 1 1

CS201 Latest Solved MCQs

Short Notes of CS201

CS201 Some Important Definitions

CS201 - Introduction to Programming Glossary By

VALLIAMMAI ENGINEERING COLLEGE

CS313D: ADVANCED PROGRAMMING LANGUAGE

Absolute C++ Walter Savitch

Written by John Bell for CS 342, Spring 2018

Quiz Start Time: 09:34 PM Time Left 82 sec(s)

Interview Questions of C++

! Errors can be dealt with at place error occurs

JAYARAM COLLEGE OF ENGINEERING AND TECHNOLOGY Pagalavadi, Tiruchirappalli (An approved by AICTE and Affiliated to Anna University)

Object-Oriented Programming (OOP) Fundamental Principles of OOP

Review. Outline. Array Pointer Object-Oriented Programming. Fall 2013 CISC2200 Yanjun Li 1. Fall 2013 CISC2200 Yanjun Li 2

Review. Outline. Array Pointer Object-Oriented Programming. Fall 2017 CISC2200 Yanjun Li 1. Fall 2017 CISC2200 Yanjun Li 2

CPSC 427: Object-Oriented Programming

CMSC 202 Section 010x Spring Justin Martineau, Tuesday 11:30am

CGS 2405 Advanced Programming with C++ Course Justification

More C++ : Vectors, Classes, Inheritance, Templates

Cpt S 122 Data Structures. Course Review Midterm Exam # 2

Object Oriented Design

OBJECT ORIENTED PROGRAMMING. Ms. Ajeta Nandal C.R.Polytechnic,Rohtak

More C++ : Vectors, Classes, Inheritance, Templates. with content from cplusplus.com, codeguru.com

Extending Classes (contd.) (Chapter 15) Questions:

Jayaram college of Engineering and Technology, Pagalavadi. CS2203 Object Oriented Programming Question Bank Prepared By: S.Gopalakrishnan, Lecturer/IT

IS 0020 Program Design and Software Tools

void fun() C::C() // ctor try try try : member( ) catch (const E& e) { catch (const E& e) { catch (const E& e) {

Data Structures and Other Objects Using C++

CS250 Intro to CS II. Spring CS250 - Intro to CS II 1

I BCS-031 BACHELOR OF COMPUTER APPLICATIONS (BCA) (Revised) Term-End Examination. June, 2015 BCS-031 : PROGRAMMING IN C ++

Midterm Review. PIC 10B Spring 2018

C++ PROGRAMMING LANGUAGE: DYNAMIC MEMORY ALLOCATION AND EXCEPTION IN C++. CAAM 519, CHAPTER 15

Polymorphism. Arizona State University 1

OOP THROUGH C++(R16) int *x; float *f; char *c;

04-24/26 Discussion Notes

Introduction to Programming Using Java (98-388)

CS304- Object Oriented Programming LATEST SOLVED MCQS FROM FINALTERM PAPERS. MC

Intro to OOP Visibility/protection levels and constructors Friend, convert constructor, destructor Operator overloading a<=b a.

STUDY NOTES UNIT 1 - INTRODUCTION TO OBJECT ORIENTED PROGRAMMING

SRM ARTS AND SCIENCE COLLEGE SRM NAGAR, KATTANKULATHUR

Introduction. Common examples of exceptions

Instantiation of Template class

Assoc. Prof. Marenglen Biba. (C) 2010 Pearson Education, Inc. All rights reserved.

mywbut.com Exception Handling

Get Unique study materials from

Inheritance, and Polymorphism.

Object-Oriented Programming

Object Oriented Design Final Exam (From 3:30 pm to 4:45 pm) Name:

Preface to the Second Edition Preface to the First Edition Brief Contents Introduction to C++ p. 1 A Review of Structures p.

Extending Classes (contd.) (Chapter 15) Questions:

AP COMPUTER SCIENCE JAVA CONCEPTS IV: RESERVED WORDS

DYNAMIC ARRAYS; FUNCTIONS & POINTERS; SHALLOW VS DEEP COPY

Inheritance, Polymorphism and the Object Memory Model


Course Text. Course Description. Course Objectives. StraighterLine Introduction to Programming in C++

C++_ MARKS 40 MIN

CS111: PROGRAMMING LANGUAGE II

엄현상 (Eom, Hyeonsang) School of Computer Science and Engineering Seoul National University COPYRIGHTS 2017 EOM, HYEONSANG ALL RIGHTS RESERVED

1. Describe History of C++? 2. What is Dev. C++? 3. Why Use Dev. C++ instead of C++ DOS IDE?

STRUCTURING OF PROGRAM

Object oriented programming. Encapsulation. Polymorphism. Inheritance OOP

Inheritance. OOP components. Another Example. Is a Vs Has a. Virtual Destructor rule. Virtual Functions 4/13/2017

KOM3191 Object Oriented Programming Dr Muharrem Mercimek OPERATOR OVERLOADING. KOM3191 Object-Oriented Programming

C++ Addendum: Inheritance of Special Member Functions. Constructors Destructor Construction and Destruction Order Assignment Operator

Babaria Institute of Technology Computer Science and Engineering Department Practical List of Object Oriented Programming with C

Exception Handling in C++

21. Exceptions. Advanced Concepts: // exceptions #include <iostream> using namespace std;

05-01 Discussion Notes

CS304 Object Oriented Programming Final Term

CSCI 102 Fall 2010 Exam #1

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

C++ Crash Kurs. Polymorphism. Dr. Dennis Pfisterer Institut für Telematik, Universität zu Lübeck

DHANALAKSHMI COLLEGE OF ENGINEERING, CHENNAI DEPARTMENT OF ELECTRICAL AND ELECTRONICS ENGINEERING CS6456 OBJECT ORIENTED PROGRAMMING

Chapter 6 Introduction to Defining Classes

+2 Volume II OBJECT TECHNOLOGY OBJECTIVE QUESTIONS R.Sreenivasan SanThome HSS, Chennai-4. Chapter -1

CSC 330 Object-Oriented Programming. Exception Handling CSC 330

Data Structures using OOP C++ Lecture 3

CPSC 427: Object-Oriented Programming

CS105 C++ Lecture 7. More on Classes, Inheritance

PIC10B/1 Winter 2014 Exam I Study Guide

COEN244: Class & function templates

Object Oriented Programming. Assistant Lecture Omar Al Khayat 2 nd Year

Suppose we find the following function in a file: int Abc::xyz(int z) { return 2 * z + 1; }

CS304 Object Oriented Programming

CSCI 102L - Data Structures Midterm Exam #1 Fall 2011

Problem Solving with C++

Introduction to Computers and C++ Programming p. 1 Computer Systems p. 2 Hardware p. 2 Software p. 7 High-Level Languages p. 8 Compilers p.

Java Object Oriented Design. CSC207 Fall 2014

C++ (classes) Hwansoo Han

IBS Software Services Technical Interview Questions. Q1. What is the difference between declaration and definition?

Object Oriented Programming with c++ Question Bank

Java Programming Lecture 7

(12-1) OOP: Polymorphism in C++ D & D Chapter 12. Instructor - Andrew S. O Fallon CptS 122 (April 3, 2019) Washington State University

AN OVERVIEW OF C++ 1

Introduction to C++ Introduction to C++ Dr Alex Martin 2013 Slide 1

Fundamental Concepts and Definitions

Transcription:

Object Oriented Programming CS250 Abas Computer Science Dept, Faculty of Computers & Informatics, Zagazig University arabas@zu.edu.eg http://www.arsaliem.faculty.zu.edu.eg

Polymorphism Chapter 8

8.1 Static and Dynamic Binding Static binding means that the address of an object is known at compile time. A statically bound function's address is known at compile time. Dynamic binding means that a single pointer can point to objects of different types. C++ permits dynamic binding, where a pointer or reference can address objects of different types as long as their classes are related by inheritance. A dynamically bound function must have its address looked up at run time. A call to a statically bound function results in faster execution than a call to a dynamically bound one.

8.2 Defining Polymorphism polymorphism is defined as the concept where a single name may denote objects of different classes that are related by some common base class. To implement polymorphism, a language must support dynamic binding. Polymorphism is so useful because it allows the programmer to manipulate instances of derived classes through a set of operations defined in their base class. Each derived class can implement the operations defined in the base class differently, while retaining a common class interface provided by the base class.

For example, let us assume that the SalariedEmployee class is derived from Employee, and that both classes contain a CalcPaycheck member function. CalcPaycheck is a simple example of the "common class interface": class Employee { public: void CalcPaycheck(); //... } ; class SalariedEmployee :public Employee { public: void CalcPaycheck(); //... };

Next, let's declare ep as an Employee pointer and assign it the address of a SalariedEmployee object. Employee * ep; ep = new SalariedEmployee; ep->calcpaycheck(); The CalcPaycheck function in the Employee class is called. In order to cause the CalcPaycheck function in the SalariedEmployee class to be called, CalcPaycheck function should be declared as a virtual function in the Employee class.

8.3 Virtual Function A virtual function is a nonstatic member function prefaced by the virtual specifier. It tells the compiler to generate code that looks up an object's type at runtime and uses this information to select the appropriate version of the function. For example, consider the CalcPaycheck function from the previous example: If the program somehow "knew" that ep pointed to a SalariedEmployee, it could have called the CalcPaycheck function in the SalariedEmployee class.

A virtual function may optionally be overridden by functions in derived classes having the same signature. The virtual specifier needs only to appear with the base class function. But it's a good idea to duplicate the virtual specifier in the derived classes as well. For example, let's suppose that both the SalariedEmployee and HourlyEmployee classes are derived from Employee:

class Employee { public: virtual void CalcPaycheck(); }; class HourlyEmployee :public Employee { public: virtual void CalcPaycheck(); }; class SalariedEmployee :public Employee { public: virtual void CalcPaycheck(); }; Employee *p0 = new Employee; Employee *p1 = new SalariedEmployee; Employee *p2 = new HourlyEmployee; P0->Calcpaycheck(); // calls Employee::CalcPaycheck() pl->calcpaycheck(); // calls SalariedEmployee::CalcPaycheck() p2->calcpaycheck(); // calls HourlyEmployee::CalcPaycheck()

Any nonstatic member function except a constructor can be virtual. Virtual functions can also be friends of other classes. Some compilers require the class destructor to be virtual if a class contains any virtual functions.

8.4 Combinations of Virtual and Non-Virtual Functions What if a non-virtual function calls a virtual function? For example, we can define the Employee and SalariedEmployee classes as follows: class Employee { public: void Display() const; // non-virtual virtual void Calcpaycheck(); // virtual }; class SalariedEmployee :public Employee { public: void Display() const; virtual void CalcPaycheck(); };

void Employee::Display(){ Calcpaycheck(); } void SalariedEmployee::Display() { CalcPaycheck(); } We invoke Display through the pointer ep. Employee *ep = new SalariedEmployee; ep->display( ) ; This causes Employee::Display() to be called, which in turn calls SalariedEmployee::CalcPaycheck(). In other words, CalcPaycheck() still works as a virtual function, although it is called by a non-virtual function.

What if a virtual function calls a non-virtual function? For example: class Employee { public: virtual void Display() const; // virtual void CalcPaycheck(); // non-virtual }; class SalariedEmployee :public Employee { public: virtual void Display() const; void CalcPaycheck(); }; Employee *ep = new SalariedErnployee; ep->display(); This causes SalariedEmployee::Display() to be called, which in turn calls SalariedEmployee::CalcPaycheck():

8.5 A Common Interface Virtual functions in a base class provide a common interface for all of its derived classes. In the Employee class, for example, we might want to define a general set of operations that get and set data member values, display an Employee, input an Employee, and process an Employee's paycheck: class Employee { public: long GetDepartment()const; long GetId() const; void SetDepartment(long deptid); void SetId(); virtual void CalcPaycheck() const; virtual void Input(); virtual void CalcPaycheck(); private: long id; long deptnum; };

Member functions that should be virtual are those functions that will be implemented in derived classes. GetId(), for example, is not virtual because it only refers to a private data member. CalcPaycheck, on the other hand, is implemented differently for each type of Employee, including those paid a monthly salary and those paid on an hourly basis.

8.6 Passing Objects by Address Virtual functions are also useful when a function parameter's type is a pointer or reference to a base class. When calling the function, we can pass a pointer or reference to an object that is of any type derived from the base class. For example: void ProcessAnyEmployee( Employee & er ) { long anid = er.getid(); // non-virtual er.calcpaycheck() ; // virtual }

Since the CalcPaycheck () is a virtual function, the particular instance of CalcPaycheck() to be called is determined at run time. Since the GetId () is not a virtual function, it will be called directly from the Employee class. Because C++ supports polymorphism, a programmer can pass an Employee, a SalariedEmployee, or any other type derived from Employee to the ProcessAnyEmployee () function.

This offers the advantage of writing a single function that handles all types of employees: For example: SalariedEmployee S; HourlyEmployee H; / /... ProcessAnyEmployee( S ); ProcessAnyEmployee( H );

The effect is the same if ProcessAnyEmployee() has an Employee * parameter: void ProcessAnyEmployee( Employee * ep ) { long anid = ep->getid(); // non-virtual ep->calcpaycheck(); // virtual } SalariedEmployee S; HourlyEmployee H; //... ProcessAnyEmployee( &S ); ProcessAnyEmployee( &H );

8.7 Virtual Destructors A virtual destructor is preceded by the virtual specifier and behaves like a virtual function. If we assume that a base class and one or more of its derived classes have destructors. we must make sure that the correct destructor is called for a base pointer that currently points to a derived object. Calling the wrong destructor could be disastrous. Particularly when it contains a delete statement: the wrong size chunk of memory might be deallocated. For this reason, we recommend that any class containing virtual functions should also have a virtual destructor.

In the next example, the BookItem class is derived from Item class and we have a pointer in BookItem that must be deallocated: class Item { public: virtual ~Item(); //. }; class BookItem :public Item { public: virtual ~BookItem(); private: char *title; }; Item *p; // base pointer p = new BookItem; // point to derived object delete p; // calls the BookItem destructor

By making the destructors virtual, we ensure that the BookItem destructor is called when we apply the delete operator to p. Destructors are not inherited, so it is wise to define one for each derived class. In our example, if we omitted the destructor from BookItem, a default destructor would automatically be created for the class, but it would not contain statements to deallocate storage pointed to by class data members.

8.8 Abstract Classes An abstract class is a class that can only be a base class for other classes. You cannot create an instance of an abstract class. Instead, it serves as a base for other classes, containing operations that are common to all of its derived classes. An abstract class either contains or inherits at least one pure virtual function. A pure virtual function is a virtual function that contains a pure-specifier, designated by the "= 0" following the function prototype:

class Shape { public: virtual void Draw() = 0; }; A pure virtual function is not implemented in the base class, but it serves as a prototype for derived classes that implement the function. In fact, a derived class must implement all pure virtual functions declared in its base class if instances of the derived class are to be created; otherwise, the derived class is automatically an abstract class.

Consider the case of the SalariedEmployee and HourlyEmployee classes. We already know that certain operations are common to both classes, such as Display, Input, and CalcPaycheck. We create an abstract class called Employee containing pure virtual member functions: class Employee { public: virtual void Display() = 0; virtual void Input() = 0; virtual void CalcPaycheck() = 0; // };

We would probably derive a number of different classes from Employee. Each of those classes would share the common interface defined here. Also, to be sure that the derived classes do not duplicate the same operations in Employee using different function names, we force those classes to override the pure virtual functions and implement the operations. Abstract classes are an ideal vehicle for presenting a class interface without letting users see the class implementation. One might decide not to place any private members in an abstract class. Only operations that comprise the interface would be described in the header file for the abstract class.

8.9 Shape Class Example The following Shape abstract class includes three operations, Draw, MoveTo, and Rotate, which are common to its derived classes: class Shape { public: }; virtual ~Shape() ; virtual void Draw() const = 0; virtual void MoveTo( int x2, int y2 ) = 0; virtual void Rotate(int degrees) = 0;

The Circle class, derived from Shape, must override each of the pure virtual functions, or it too will be considered an abstract class: class Circle: public Shape { public: Circle() ; Circle(const Point & acenter, float aradius ); virtual ~Circle(); virtual void Draw() const; virtual void MoveTo( int x2. int y2 ); virtual void Rotate{ int degrees ); private: Point center; float radius; };

The Polygon class, on the other hand, is an abstract class because we have not implemented all of the pure virtual functions from the Shape class: class Polygon :public Shape { public: Polygon() ; Polygon ( Point & cent, Point * verts }; virtual ~Polygon(); private: Point center; Point * vertices; // array of Points };

Pure virtual functions provide a good mechanism to prevent the inadvertent omission of a essential operations in derived classes. If we tried, for example, to create an instance of Circle, and if Circle did not contain a Rotate function, the compiler would issue an error saying that it could not create an instance of an abstract class.

8.10 Exception Handling Exception handling is a sophisticated way to handle runtime errors in C++. Rather than aborting a program and leaving objects in an undefined (or corrupted) state, exception handling gives us the ability to perform a more graceful recovery from errors. Exception handling lets us handle an error at different levels, providing context-specific information that can be used as an aid to fixing the problem that caused the exception.

In C++, errors such as memory exhaustion, subscript range errors, or division by zero are called exceptions. The range and definition of these errors, as well as the way the errors are handled, can be programmer-defined. In C++, when an exception is generated, the error cannot be ignored or the program will terminate.

If error handling code is in place for a particular type of error, the program has the option of recovering from the error and continuing execution. A program throws an exception at the point where an error is first detected. When this happens, a C++ program automatically searches for a block of code called an exception handler, which responds to the exception in some appropriate way. This response is called catching an exception. If an exception handler cannot be found, the program simply terminates.

Throw, Catch, and Try Many different types of exceptions can occur, so when an exception is thrown, a throw expression (or throw point) identifies the type of exception. Example: the following throws an exception when a subscript is out of bounds: const unsigned ArraySize = 500; unsigned i; if( i >= ArraySize ) // subscript valid? throw RangeError(); // no: throw an exception

RangeError is not a standard exception class, so it must be defined within the current scope. This version of RangeError has no data or function members, but other exeception classes often do: class RangeError{ }; // exception class

The try keyword, along with statements falling within { } braces is called a try block. It must be immediately followed by one or more exception handlers. Each exception handler begins with the catch keyword, followed by a block containing statements. The following shows the format of a try block followed by two handlers: try { statement-list } catch ( parameter-list){ statement-list } catch ( parameter-list){ statement-list }

The most likely parameter is an exception object, usually passed by constant reference, such as: const RangeError & R. An exception can only be thrown after a program's execution has entered a try block. The throw expression might be physically inside the block, or it might be nested in functions called from the try block. In the next example, TestTheArray calls InsertValue from a try block. Inside InsertValue, if i is too large, a RangeError exception is thrown and control immediately passes to the handler in TestTheArray. An error message is displayed and the program continues without having corrupted memory with an out-of-range subscript: const unsigned ArraySize = 50; int array[arraysize]; //

void InsertValue( unsigned i, int value){ if( i >= ArraySize ) throw RangeError(); array[i] = value; } void TestTheArray(){ unsigned j; int anint; cout «"Enter a subscript and a value: "; cin» j» anint; try { InsertValue( j, anint ); } catch( const RangeError & ) { cout «"Range error in TestTheArray()"; throw; }}

In this example, the handler throws the same exception object backward to the previous context, which is the function that called TestTheArray. This re-throwing of the exception is optional, but helpful when the program must back up through nested function calls, possibly all the way to main. When an exception is thrown, a C++ program backs up all the way to main until a handler is found, or the program terminates.

Unwinding the Execution Stack When a program throws an exception, the destructor is called for each object that was constructed from the time the program entered a try block. This process is called stack unwinding, and it is a major strength of the exception handling mechanism. Example: if an exception is thrown while creating the LongArray object, the file stream's destructor is called first, then the handler executes: try { ofstream log("log.txt"); LongArray L(30000); } catch( xalloc ){ cout «"Unable to create LongArray"; }

When an exception is thrown during the construction of a composite object, destructors will be invoked only for those data members that have already been constructed. Similarly, if an exception is thrown during the construction of an array of objects, destructors are invoked only for those array elements that have already been constructed. Example: the Student class contains VString and Transcript data members. The student's name will be constructed first, followed by the records data member: class VString {...}; class Transcript { }; class Student { private: VString lastname; Transcript records; };

int main ( ) { try { VString collegename("computers & Infomatics"); Student S; } catch (... ) { / /... } assume that an exception is thrown by the Transcript constructor. First, the VString destructor is invoked for collegename, Followed by the same destructor for S.lastName. But the Transcript destructor is not invoked because the records data member was only partially constructed.

If an exception is thrown again while a destructor is executing, terminate is called. Also, if a handler cannot be found for a thrown exception, terminate is called. when terminate is called, standard C++ does not specify whether or not the stack is unwound, so destructors for existing class objects might not be called.

8.11 Debugging Tips Avoiding Calls to new in User Code Consistent with block scope rules, any object declared in a try block is not accessible outside the block. This creates an interesting problem when statements within a try block perform memory allocation.

Example: if the first array of characters is successfully allocated but the second array allocation fails, pc1 goes out of scope without letting us deallocate the memory it addresses: const unsigned size1 = 500; const unsigned size2 = 30000; try { char *pc1 = new char[size1]; char *pc2 = new char[size2]; } catch ( xalloc ){ cout «"Allocation error"; }

To prevent this type of problem, we can avoid directly calling the new operator in user code. Wrap all memory allocations inside classes. So whenever an exception is thrown, each object's destructor takes care of its own memory deallocation.

rewrite the foregoing example, this time using DynString objects to hold the two character arrays. In a test run of the program, object pc1 was allocated successfully, but pc2 was not. The output from the program was Created string at: 0x0dc2 Deleted string at: 0x0dc2 Allocation error caught. By comparing the program to its output, we see that an exception was thrown while attempting to allocate pc2, so the destructor for pc1 was called. Finally, the handler was executed.

#include <iostream.h> #include <except.h> const unsigned size1 = 500; const unsigned size2 = 30000; class DynString{ public: DynString(unsigned strsize); ~DynString(); private: char *str; unsigned size; }; DynString:: DynString(unsigned strsize){ size=strsize; str=new char[strsize]; cout<< Created string at: <<hex<<&str<<endl; }

DynString::~ DynString(){ delete [] str; cout<< Deleted string at: <<hex<<&str<<endl; } int main(){ try { DynString pc1(size1); DynString pc2(size2); cout<< Both allocations successful \n ; } catch(xalloc){ cout<< Allocation error caught. ; } return 0; }