Chapter 5. Object- Oriented Programming Part I

Similar documents
Chapter 3. Object-Based Programming Part I

POLYMORPHISM 2 PART Abstract Classes Static and Dynamic Casting Common Programming Errors

POLYMORPHISM 2 PART. Shared Interface. Discussions. Abstract Base Classes. Abstract Base Classes and Pure Virtual Methods EXAMPLE

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

Absolute C++ Walter Savitch

Polymorphism. Zimmer CSCI 330

Instantiation of Template class

CPSC 427: Object-Oriented Programming

QUIZ. Write the following for the class Bar: Default constructor Constructor Copy-constructor Overloaded assignment oper. Is a destructor needed?

VIRTUAL FUNCTIONS Chapter 10

Resource Management With a Unique Pointer. Resource Management. Implementing a Unique Pointer Class. Copying and Moving Unique Pointers

What are the characteristics of Object Oriented programming language?

Chapter 5 Object-Oriented Programming

OOPS Viva Questions. Object is termed as an instance of a class, and it has its own state, behavior and identity.

Inheritance, and Polymorphism.

2 ADT Programming User-defined abstract data types

C++ Important Questions with Answers

Object Oriented Programming in Java. Jaanus Pöial, PhD Tallinn, Estonia

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

C++ Programming: Polymorphism

Contents. I. Classes, Superclasses, and Subclasses. Topic 04 - Inheritance

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

And Even More and More C++ Fundamentals of Computer Science

Introduction to Inheritance

Inheritance, Polymorphism and the Object Memory Model

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

Cpt S 122 Data Structures. Course Review FINAL. Nirmalya Roy School of Electrical Engineering and Computer Science Washington State University

Java: introduction to object-oriented features

Object Oriented Software Design II

Object Oriented Software Design II

Introduction to Programming Using Java (98-388)

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

OBJECT ORIENTED PROGRAMMING USING C++

RAJIV GANDHI COLLEGE OF ENGINEERING AND TECHNOLOGY DEPARTMENT OF INFORMATION TECHNOLOGY OBJECT ORIENTED PROGRAMMING QUESTION BANK UNIT I 2 MARKS

Data Abstraction. Hwansoo Han

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

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

Weiss Chapter 1 terminology (parenthesized numbers are page numbers)

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

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

Programming Language Concepts Object-Oriented Programming. Janyl Jumadinova 28 February, 2017

Increases Program Structure which results in greater reliability. Polymorphism

Polymorphism Part 1 1

Programming II (CS300)

Polymorphism. Miri Ben-Nissan (Kopel) Miri Kopel, Bar-Ilan University

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

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

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

UNIT 3 ARRAYS, RECURSION, AND COMPLEXITY CHAPTER 11 CLASSES CONTINUED

Argument Passing All primitive data types (int etc.) are passed by value and all reference types (arrays, strings, objects) are used through refs.

Paytm Programming Sample paper: 1) A copy constructor is called. a. when an object is returned by value

Graphical Interface and Application (I3305) Semester: 1 Academic Year: 2017/2018 Dr Antoun Yaacoub

What s Conformance? Conformance. Conformance and Class Invariants Question: Conformance and Overriding

Chapter 6. Object- Oriented Programming Part II

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

1 Shyam sir JAVA Notes

CGS 2405 Advanced Programming with C++ Course Justification

Object Oriented Programming with c++ Question Bank

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

VALLIAMMAI ENGINEERING COLLEGE

Java Inheritance. Written by John Bell for CS 342, Spring Based on chapter 6 of Learning Java by Niemeyer & Leuck, and other sources.

CLASSES AND OBJECTS IN JAVA

COMP6771 Advanced C++ Programming

CS250 Final Review Questions

Programming in C# Inheritance and Polymorphism

Design issues for objectoriented. languages. Objects-only "pure" language vs mixed. Are subclasses subtypes of the superclass?

Object-Oriented Programming

Programming C++ Lecture 5. Howest, Fall 2013 Instructor: Dr. Jennifer B. Sartor

Handout 9 OO Inheritance.

CPSC 427: Object-Oriented Programming

Starting Savitch Chapter 10. A class is a data type whose variables are objects. Some pre-defined classes in C++ include int,

Data type of a pointer must be same as the data type of the variable to which the pointer variable is pointing. Here are a few examples:

IS 0020 Program Design and Software Tools

Overview. Constructors and destructors Virtual functions Single inheritance Multiple inheritance RTTI Templates Exceptions Operator Overloading

Inclusion Polymorphism

04-24/26 Discussion Notes

Practice for Chapter 11

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

CH. 2 OBJECT-ORIENTED PROGRAMMING

class Polynomial { public: Polynomial(const string& N = "no name", const vector<int>& C = vector<int>());... };

Distributed Real-Time Control Systems. Chapter 13 C++ Class Hierarchies

Java Fundamentals (II)

6 Architecture of C++ programs

OOPs Concepts. 1. Data Hiding 2. Encapsulation 3. Abstraction 4. Is-A Relationship 5. Method Signature 6. Polymorphism 7. Constructors 8.

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

CMSC 132: Object-Oriented Programming II

Problem Solving with C++

Chapter 11. Categories of languages that support OOP: 1. OOP support is added to an existing language

What is Inheritance?

Overview. Constructors and destructors Virtual functions Single inheritance Multiple inheritance RTTI Templates Exceptions Operator Overloading

Chapter 6 Introduction to Defining Classes

Tokens, Expressions and Control Structures

CPSC 427: Object-Oriented Programming

STRUCTURING OF PROGRAM

Polymorphism. Contents. Assignment to Derived Class Object. Assignment to Base Class Object

AP COMPUTER SCIENCE JAVA CONCEPTS IV: RESERVED WORDS

Object Oriented Programming. Solved MCQs - Part 2

Object-Oriented Principles and Practice / C++

C++ Inheritance and Encapsulation

Object-oriented Programming. Object-oriented Programming

Transcription:

Chapter 5 Object- Oriented Programming Part I

5: Preview basic terminology comparison of the Java and C++ approaches to polymorphic programming techniques introduced before in the context of inheritance: destructing objects, overloading assignment operators, overloading operations, and exception handling abstract classes, and Template Method design pattern a friend operation and class

5: Basic Terminology and a Derived Class Definition Class D extends another class B: D is called a derived class of B B is called a base class of D (B is also called a superclass for the subclass D). BankAccount class has two derived classes: CheckingAccount and SavingsAccount. B D

5: Basic Terminology and a Derived Class Definition Java C++ Comments about C++ class D extends B { class D extends B { class D extends B { class D: public B { class D: private B { class D:protected B { A public inheritance A private inheritance A protected inheritance super -- C++ does not support super final -- C++ does not support final

5: Public Inheritance Public inheritance: a derived class wants to inherit the entire public interface of its base class (same as Java inheritance). All features that are public in the base class can be used by the derived class.

class Student { public: Public Derivation Student(long = 0, string = ""); long getnumber() const; string getname() const; void printinfo() const; private: long number_; string name_; }; Public derivation class StudentWithAccount : public Student { // no extends public: StudentWithAccount(long, string, double = 0.0); double getbalance() const; void setbalance(double); void printinfo() const; private: double balance_; Last slide };

5: Creating Objects The constructor of a derived class must first take care of the initialization of the attributes of its base class, using syntax similar to the member initialization list: StudentWithAccount::StudentWithAccount(long number, string name, double balance) : Student(number, name) // base class' constructor { balance_ = balance; } StudentWithAccount::StudentWithAccount(long number, string name, double balance) : Student(number, name), balance_(balance) { } // alternative implementation

Derived Class Constructor The constructor of a derived class D calls the constructor of the base class B using syntax similar to the member initialization list: : B(parameters)

5: RTTI and Type Conversions Java: a powerful reflection mechanism C++: a modest set of operations, Run-Time Type Identification, RTTI to allow you to find the current type of the value of a pointer or a reference, whose declared type is of some base class. There are two basic RTTI mechanisms: - a dynamic cast, - typeid RTTI works only if used for classes that have at least one virtual function. In general, RTTI should be avoided and often can be replaced by using polymorphic operations.

5: Downcasting Pointers and references to a base class can be assigned objects of a derived class without using any explicit cast: Student* ps = new StudentWithAccount(40, "john", 2000); Student& s = StudentWithAccount(30, "barbara", 1000); cout << s.getname(); cout << s.getbalance(); cout << ps->printinfo(); // can't access derived class // calls Student::printInfo() Student's code

5: dynamic_cast To find the type of the variable value at run-time: dynamic_cast<t>(p) If p points to some object of type T, then the above expression returns p converted to T, and 0 otherwise. This downcast can be applied only to pointers: Student* ps;... // initialize ps StudentWithAccount* pswa; if(pswa = dynamic_cast<studentwithaccount*>(ps)) { cout << pswa->getbalance(); pswa->printinfo(); // calls StudentWithAccount::printInfo(); } else // pswa is 0

5: dynamic_cast There are several reasons for which dynamic cast should be avoided: it is a run-time operation, more expensive than a compile-time operation, and it may be difficult to come up with good error handling if this cast fails downcasting using dynamic cast makes program extensibility and maintenance more difficult, because you have to make assumptions about the inheritance hierarchy, and if this hierarchy changes, your code will likely break.

5: Upcast Upcast: moving up the inheritance tree a cast from a derived class to a base class (allowed only for a public inheritance): void print(student s) { s.printinfo(); } StudentWithAccount swa(30, "barbara", 1000); print(swa); // swa is upcast'ed; s = (Student)swa Results in a slice of the object swa being copied to the object s Calls Student::printInfo() rather than StudentWithAccount::printInfo()

5: Slicing Student(long = 0, string = ""); long getnumber() const; string getname() const; void printinfo() const; long number_; string name_; StudentWithAccount(long, string, double = 0.0); double getbalance() const; void setbalance(double); void printinfo() const; double balance_; swa Student(long = 0, string = ""); long getnumber() const; string getname() const; void printinfo() const; long number_; string name_; swa sliced to Student

5: Copy Constructors The syntax used to define a constructor in a derived class is also used to define a copy constructor; for example: Student::Student(const Student&) {... } StudentWithAccount(const StudentWithAccount& swa) : Student(swa) { balance_ = swa.balance_; Call base class' copy } constructor

5: Scope and Visibility Modifiers Using public inheritance: a derived class inherits all of the public features of the base class private features of the base class are not accessible in the derived class void StudentWithAccount::printInfo() const { cout << "Student number:" << number_ << "; name:" << name_ << "; balance:" << balance_ << endl; } any future changes to the private part of the base class do not affect a derived class known as inheriting the interface, but not the implementation

5: Scope and Visibility Modifiers (cont.) You can use the scope operator :: to refer to a public feature in a base class that has the same name as a feature in a derived class: void StudentWithAccount::printInfo() const { Student::printInfo(); // access feature from base class cout << "balance:" << balance_ << endl; }

5: Protected Interface As in Java, a C++ class has a public interface, and a protected interface. A class feature may be qualified as protected: private for the instantiating clients accessible to its derived classes. A protected feature f may be accessed in member operations of a derived class only in the following two contexts: - direct access of the form: f or this->f - indirect access of the form: ref.f or ref->f, where ref is (or, points to) an instance of a derived class.

5: Protected Interface (cont.) If both number_ and name_ in the class Student are protected: void StudentWithAccount::printInfo() const { cout << "Student number:" << number_ << "; name:" << name_ << "; balance:" << balance_ << endl; } void StudentWithAccount::info(const Student& s, const StudentWithAccount& swa) { cout << s.number_; // can't access through Student cout << swa.number_; // can through StudentWithAccount }

In Java, all operations that are not final employ late binding. Given a variable var and the call var.foo() 5: Polymorphism and Virtual Functions it is the value of var, and not its type that is used to find foo(). If the value of the variable is an object of a derived class that redefines an operation defined in a base class, then this redefined operation is invoked. For final operations, Java uses early binding: the type of the class variable, and not its value, determines which operation is invoked. C++ uses a different philosophy: by default, early binding is used. Late binding is used only for pointers or references, and only if the operation is explicitly specified as virtual

5: Polymorphism and Virtual Functions (cont.) Student s(10, "kasia"); Student* ps = new Student(20, "michael"); StudentWithAccount sw(30, "barbara", 1000); StudentWithAccount* psw = new StudentWithAccount(30, "mary", 0); Student* pstud = new StudentWithAccount(40, "john", 2000); s.printinfo(); // Student::printInfo ps->printinfo(); // Student::printInfo sw.printinfo(); // StudentWithAccount::printInfo psw->printinfo(); // StudentWithAccount::printInfo pstud->printinfo(); // Student::printInfo Student's code

5: Polymorphism and Virtual Functions (cont.) In order to use late binding, printinfo() must be made virtual: class Student { public:... virtual void printinfo() const; }; void Student::printInfo() const { // don't repeat virtual cout << "Student number:" << number_ << "; name:" << name_ << endl; } class StudentWithAccount : public Student { public: virtual void printinfo() const; // virtual

void StudentWithAccount::printInfo() const { } 5: Polymorphism and Virtual Functions (cont.) cout << "Student number:" << number_ << "; name:" << name_ << "; balance:" << balance_ << endl; void StudentWithAccount::printInfo() const { Student::printInfo(); cout << "balance:" << balance_ << endl; } because the scope operator turns off late binding.

Virtual 1. When a virtual operation is invoked from the base class' constructor, then it is not really virtual (i.e. early binding is used). 2. A virtual operation in a derived class must have an operation signature identical to the corresponding operation signature in a base class (with the exception of Covariant Return Types)

5: Destructing Objects Destructors: are not inherited you cannot explicitly call a destructor of a base class in the definition of a destructor of the derived class it is easy to end up writing a destructor that will only be called for the base class; a grave mistake if the derived class has any resources that need to be released.

Virtual Destructor When you design a class, make the destructor virtual; otherwise, it may be difficult or even impossible to design derived classes that clean up all memory. If this base class has no resources, then make the destructor's body empty.

class AccountForStudent { public: Virtual destructor virtual ~AccountForStudent();... protected: Student* stud_; }; AccountForStudent::~AccountForStudent() { delete stud_;} class Bank; class BankAccount : public AccountForStudent { public: virtual ~BankAccount();... protected: Bank* bank_; }; BankAccount::~BankAccount() { delete bank_; }

5: Destructing Objects AccountForStudent* ba = new BankAccount("John", 100, 1200.50, new Bank("Royal Bank")); maintains two resources: a bank and a student. For delete ba; the value of ba is used (late binding), and so the destructor of the derived class gets called. When the destructor of a derived class completes, the destructor of the base class gets called.

5: Overloaded Assignments

class AccountForStudent { public: Overloaded Assignment AccountForStudent& operator=(const AccountForStudent&); protected: Student* stud_; }; AccountForStudent& AccountForStudent::operator=( const AccountForStudent& as) { if(this == &as) return *this; delete stud_; stud_ = new Student(as.stud_->getNumber(), as.stud_->getname()); balance_ = as.balance_; return *this; }

class BankAccount : public AccountForStudent { public: Overloaded assignment BankAccount& operator=(const BankAccount&); protected: Bank* bank_; }; BankAccount::operator=(const BankAccount& b) { if(this == &b) return *this; AccountForStudent::operator=(b); // assign base part // copy bank delete bank_; bank_ = new Bank(b.bank_->getName()); return *this; }

Overloaded Assignment in Derived Class An overloaded assignment operator in a derived class must make an explicit call to the overloaded assignment operator in the base class.

5: Overloading Overloading an operation in a derived class means that the operation from the base class becomes inaccessible: class IntegerReadOnly { public: explicit IntegerReadOnly(int); int value() const; // query protected: int value_; }; class Integer : public IntegerReadOnly { public: explicit Integer(int); int value(int); // modifier, returns new value };

5: Overloading Integer i(10); cout << i.value(5); // modifier: sets the value to 5 cout << i.value(); // wrong; accessor is hidden To provide access to the hidden operation from the base class: Or: int Integer::value() { return IntegerReadOnly::value(); } using BaseClass::featureName; // no brackets

5: Overloading class Integer : public IntegerReadOnly { public: Integer(int); int value(int); // modifier using IntegerReadOnly::value; // int value() accessible }; cout << i.value(5); // modifier: sets the value to 5 cout << i.value(); // accessor

5: Overriding Overriding virtual functions is used to achieve polymorphism. The signature of a virtual operation in a derived class must be identical to the signature of this operation defined in the base class: class IntegerMutable { public: IntegerMutable(int); virtual int value(int = 0); //modifier, returns value protected: int value_; };

5: Overriding class Integer : public IntegerMutable { public: Integer(int); virtual int value() const; // different signature }; IntegerMutable* i = new Integer(10); cout << i->value(); // modifier: sets the value to 0 The query operation value() is invoked from the base class because it is overloaded instead of being overridden.

5: Covariant Return Types If a virtual operation in the base class returns a reference or a pointer to a class type, then signatures in the base class and in the derived class don't have to be strictly identical: class Base { class Derived : public Base { public: public: virtual Base* foo(); virtual Base* foo(); virtual Base* goo(); virtual Derived* goo();... void doo(); }; };

5: Covariant Return Types Base* p = new Derived; p->goo()->doo(); p->foo()->doo(); // foo()'s return type is Base if(derived* d = dynamic_cast<derived*>(p->foo())) d->doo();

Overloading and Overriding 1. Overriding: --A non-virtual operation in a derived class hides an operation with the same signature in an ancestor class. --The hidden operation can be made available through the using keyword. --The implementation of a virtual operation can be replaced in a derived class, provided that the signature is not changed 2. Overloading works only within the scope of a single class

5: Passing Parameters by Value and by Reference When a parameter of an operation is passed by value, and the type of the formal parameter is a base class of the type of the actual parameter, then the resulting slicing that occurs may create a problem: class Shape { public: virtual void display() const;... }; class SpecificShape : public Shape { public: virtual void display() const;... };

5: Passing Parameters by Value and by Reference void display(shape s) {... s.display(); } SpecificShape ss; display(ss); // the parameter s is sliced The call s.display() invokes Shape::display() rather than SpecificShape::display(). Passing parameters by reference avoids these problems: void display(const Shape& s);

5: Standard Exceptions The C++ standard library defines a hierarchy of exceptions, with exception as the root, used by operations in this library. Can also be used in any user defined program (include <stdexcept>). Exceptions are divided into: logic errors: static errors that can be prevented and detected at compile time run-time errors: dynamic errors that can be detected only at run-time. Derived classes of logic errors use self-explanatory names: invalid_argument exception should be used if an operation receives a parameter with an invalid value, such as 0.

5: Standard Exceptions

5: Standard Exceptions exception has an operation: virtual const char* what() const throw(); Each of the exception classes has an explicit constructor, used to specify the value returned by what(): logic_error::logic_error(const string& argumentforwhat); There is a similar arrangement for run-time errors.

class IntStack { public: IntStack(int = 100); IntStack // default size IntStack(const IntStack&); virtual ~IntStack(); IntStack& operator=(const IntStack&); void push(int) throw(logic_error); int pop() throw(logic_error); private: int top_; int* stack_; int size_; }; void IntStack::push(int i) throw(logic_error) { if(top_ == size_ - 1) // full throw logic_error("stack full "); stack_[++top_] = i; }

5: Resource Management, Part II Throwing an exception results in an unwinding of the run-time stack, which means that all objects created between the time the exception is thrown and caught are destroyed through a call to their destructors. thrown objects time caught: Destruct!

5: Resource Management, Part II (cont.) try { IntStack* s = new IntStack(20); s->push(20); } catch(const bad_alloc&) { cout << "ran out of memory" << endl; } catch(const logic_error& e) { cout << e.what() << endl; }

5: Resource Management, Part II (cont.) You can create a wrapper class Resource for a pointer to a resource: typedef Resource* ResourcePointer; class ResourceHandle { public: ResourceHandle(const ResourcePointer&); virtual ~ResourceHandle(); operator ResourcePointer() const; private: ResourcePointer handle_; ResourceHandle(const ResourceHandle&); ResourceHandle& operator=(const ResourceHandle&); };

ResourceHandle::ResourceHandle(const ResourcePointer &r) : handle_(r) {} ResourceHandle::~ResourceHandle() { delete handle_; 5: Resource Management, Part II (cont) } ResourceHandle::operator ResourcePointer() const { return handle_; } - makes implicit type conversions possible: ResourceHandle r(new ResourcePointer()); void op(resourcepointer); op(r); // gets converted to op(r.handle_)

5: Resource Management, Part II (cont) void foo() { Resourcehandle r(new Resource); op(r);... } If an exception is thrown in foo(), then the function will terminate and all local destructors will be called. In particular, the destructor for r will be called, releasing the handle_ resource.

5: Abstract Operations and Classes Java C++ Comments about C++ class A { abstract void f(); class A { virtual void f()=0; Pure virtual operation, with empty body is abstract abstract class A class A { // abstract virtual void f()=0; interface Ifc class Ifc { //interface virtual void f()=0; class Imp implements Ifc class Imp : public Ifc { // implements A class with at least one pure virtual operation A class with all operations that are pure virtual A derived class that implements all abstract operations

5: Benchmark class BenchmarkClass { // abstract public: virtual void benchmark() const = 0; double repeat(long count) const; }; #include <ctime> #include "ex4.4.benchmarkclass.h" double BenchmarkClass::repeat(long count) const { time_t start, finish; time(&start); for(long loop = 0; loop < count; ++loop) benchmark(); time(&finish); return difftime(finish, start); }

class MyBenchmarkClass : public BenchmarkClass { public: Benchmark virtual void benchmark() const; }; void MyBenchmarkClass::benchmark() const { double res = 1.23 * 4.56; } BenchmarkClass* b = new MyBenchmarkClass(); cout << b->repeat(10000000); // implements Here - an abstract class has a complete interface, and only provides the implementation of those operations that can be specified at this general level. These implementations may use other operations defined in this class, both concrete and abstract - the derived classes are responsible for implementing the abstract operations.

5: Template Method Design Pattern If you have two similar operations in a class, you can define a single common operation in the base class. Operations that are not similar are expressed as abstract, to be defined in derived classes. The template method design pattern: the template method defines the algorithm in terms of abstract operations, called the primitive operations. The Template Method Design Pattern is an example of a class behavioral pattern, because it describes class behavior. In general, behavioral design patterns describe patterns of objects, classes, and the communication between them. There are two kinds of behavioral patterns: class patterns that use inheritance, and object patterns that use object composition

5: Template Method Design Pattern (cont.) The Template Method Design Pattern: - one or more abstract (primitive) operations that represent the missing information; - remaining template methods use these abstract operations. The derived classes are responsible for implementing these abstract operations

5: Template Method Design Pattern (cont.) Examples of template method design pattern: the implementation of sorting algorithms, defined in terms of a primitive compare() operation to compare two elements. The abstract base class has a template method sort(), which uses compare(). Various derived classes of this class then define different ways of comparing elements. a class responsible for logging users into an application; the login operation is a template method and consists of four steps: - prompting for the user id and password (concrete) - authenticating the user (primitive) - displaying appropriate information while the authentication is in progress (concrete) - notification that the login is complete (primitive).

5: Template Method Design Pattern (cont.) the template method should not be overridden, and therefore it is not defined as virtual all operations that are used by the template method are defined as virtual, as well as private or protected, so that the client cannot directly call them. a derived class may also redefine (override) other concrete operations: concrete operations overridden in derived classes are called hook operations. In Java s java.io.reader class, read() is a hook operation, overridden in java.io.inputstreamreader.

5: Postponing Creation of Objects 1. By specifying at least one operation as abstract (i.e. pure virtual) 2. By specifying constructors as private or protected 3. Defining a pure virtual destructor: class B { public: virtual ~B() = 0;... }; B::~B() { }

Consider two classes, which cooperate to perform a certain task: List and ListElement. 5: Friends The class List needs access to the private attributes of the class ListElement, and it would be inefficient to use queries and modifiers for this purpose. C++ provides a friend declaration, using which the class may declare that one of the following constructs is a friend and therefore has access to private features of this class: - another class - a single operation from another class - a global operation.

ListElem gives access to its private features to the entire List: class ListElem { friend class List;... }; // gives access to List To give access to a specific operation in this class, say show(): class ListElem { friend void List::show();... }; To give access to a global function print() class ListElem { friend void ::print();... }; 5: Friends (cont.) // gives access to show() // gives access to print()

5: Friends (cont.) external operations specified as friends are not a part of a class interface, but they have the same access rights as regular class operations friendship is limited to the class specified as a friend. When you declare that X is a friend, you do not give special privileges to X's friends friendship is not transitive (nor is it symmetric: If Y is a friend of X then X is not automatically a friend of Y) a derived class of X is not considered to be a friend friendship cannot be declared for an existing class, because only this class can specify it. Note that friends do not completely break encapsulation; but you should avoid declaring friendship unless absolutely necessary