Advanced Programming & C++ Language

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

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

C++ Programming: Polymorphism

ECE 3574: Dynamic Polymorphism using Inheritance

Inheritance, Polymorphism and the Object Memory Model

15: Polymorphism & Virtual Functions

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

Object-Oriented Programming, Iouliia Skliarova

Polymorphism Part 1 1

Increases Program Structure which results in greater reliability. Polymorphism

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

Software Engineering Design & Construction

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

OBJECT ORIENTED PROGRAMMING USING C++

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

Polymorphism. Zimmer CSCI 330

Outline. Java Models for variables Types and type checking, type safety Interpretation vs. compilation. Reasoning about code. CSCI 2600 Spring

Dynamic Binding C++ Douglas C. Schmidt

Software Engineering Design & Construction Dr. Michael Eichberg Fachgebiet Softwaretechnik Technische Universität Darmstadt

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

Virtual functions concepts

G52CPP C++ Programming Lecture 13

Object typing and subtypes

What are the characteristics of Object Oriented programming language?

Java Object Oriented Design. CSC207 Fall 2014

Lecture 13: Object orientation. Object oriented programming. Introduction. Object oriented programming. OO and ADT:s. Introduction

These new operators are intended to remove some of the holes in the C type system introduced by the old C-style casts.

CS107 Handout 37 Spring 2007 May 25, 2007 Introduction to Inheritance

Tokens, Expressions and Control Structures

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

Fast Introduction to Object Oriented Programming and C++

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

Chapter 6 Introduction to Defining Classes

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

Announcements. Subtype Polymorphism, Subtyping vs. Subclassing, Liskov Substitution Principle. Intuition: Type Signature is a Specification.

INHERITANCE & POLYMORPHISM. INTRODUCTION IB DP Computer science Standard Level ICS3U. INTRODUCTION IB DP Computer science Standard Level ICS3U

CPS 506 Comparative Programming Languages. Programming Language

Software Engineering Design & Construction

CS-202 Introduction to Object Oriented Programming

Introduction to Programming Using Java (98-388)

C++ without Classes. CMSC433, Fall 2001 Programming Language Technology and Paradigms. More C++ without Classes. Project 1. new/delete.

C-style casts Static and Dynamic Casts reinterpret cast const cast PVM. Casts

Day 4. COMP1006/1406 Summer M. Jason Hinek Carleton University

Object Oriented Software Design II

Object Oriented Software Design II

Absolute C++ Walter Savitch

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

QUIZ. How could we disable the automatic creation of copyconstructors

Chapter 15. Polymorphism and Virtual Functions. Copyright 2010 Pearson Addison-Wesley. All rights reserved

QUIZ. How could we disable the automatic creation of copyconstructors

Inheritance and Polymorphism

Short Notes of CS201

Why use inheritance? The most important slide of the lecture. Programming in C++ Reasons for Inheritance (revision) Inheritance in C++

Lecture 11 Subtypes and Subclasses

Object-oriented Programming. Object-oriented Programming

CS201 - Introduction to Programming Glossary By

CSE 331 Software Design and Implementation. Lecture 12 Subtypes and Subclasses

G Programming Languages - Fall 2012

Chapter 11 Inheritance and Polymorphism. Motivations. Suppose you will define classes to model circles,

Software Paradigms (Lesson 3) Object-Oriented Paradigm (2)

Instantiation of Template class

Inheritance and Interfaces

The Java Programming Language

CSE 331 Software Design & Implementation

Inheritance, and Polymorphism.

Inclusion Polymorphism

Lecture 3. COMP1006/1406 (the Java course) Summer M. Jason Hinek Carleton University

COMP322 - Introduction to C++ Lecture 09 - Inheritance continued

1: Introduction to Object (1)

Inheritance and Polymorphism

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

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

Data Abstraction. Hwansoo Han

Week 7. Statically-typed OO languages: C++ Closer look at subtyping

C++ Yanyan SHEN. slide 1

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)

C++ Inheritance II, Casting

Object-Oriented Programming

Inheritance and Encapsulation. Amit Gupta

Java Fundamentals (II)

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

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

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

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

Inheritance, polymorphism, interfaces

CS11 Advanced C++ Fall Lecture 7

OBJECT ORİENTATİON ENCAPSULATİON

Concepts of Programming Languages

CS3157: Advanced Programming. Outline

Rules and syntax for inheritance. The boring stuff

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

CSE 331 Software Design & Implementation

Object Oriented Programming is a programming method that combines: Advantage of Object Oriented Programming

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

What is Inheritance?

QUIZ. What is wrong with this code that uses default arguments?

History C++ Design Goals. How successful? Significant constraints. Overview of C++

CS558 Programming Languages Winter 2013 Lecture 8

Weiss Chapter 1 terminology (parenthesized numbers are page numbers)

Transcription:

Advanced Programming & C++ Language ~2~ Inheritance Polymorphism Ariel University 2018 Dr. Miri (Kopel) Ben-Nissan

Inheritance

class Employee { private: char* m_sfirstname, m_slastname; Date m_hiringdate; short m_sidepartment; // public: // void SetHiringDate(int dd,int mm,int yy); void SetDepartment(short department); // }; 3 How should we describe a Manager? A manager is also an employee. Has more attributes than Employee. Miri Kopel, Bar-Ilan University

class Manager : public Employee { private: Employee* m_employeegroup; short //... }; m_silevel; Employee Base class (super class) Deriving Manager from Employee in this way makes Manager a subtype of Employee so that a Manager can be used wherever an Employee is acceptable. 4 Manager Derived class (subclass)

Constructors and Destructors 5 Class objects are constructed from the bottom up: 1. The base. 2. The members. 3. The derived class itself. They are destroyed in the opposite order: 1. The derived class itself. 2. The members. 3. The base.

Inheritance (cont ) 6 Inheritance comes in two forms, depending on number of parents a subclass (derived class) has: Single Inheritance (SI) Only one parent per derived class. Form an inheritance tree. SI requires a small amount of run-time overhead when used with dynamic binding. Multiple Inheritance (MI) More than one parent per derived class. Forms an inherited DAG (Directed Acyclic Graph). Compared with SI, MI adds additional run-time overhead (also involving dynamic binding).

Inheritance (cont ) A derived class can itself be a base class. 7 Employee Employee Temporary Secretary Manager Temporary Secretary Manager Director (a) S.I. Consultant Director (b) M.I.

8 Types of Inheritance Subtyping/Interface Inheritance: creating a subtype of an existing class for purpose of setting up dynamic binding. Circle is a subclass of Shape (i.e., Is-A relation). A Birthday is a subclass of Date.

Types of Inheritance (cont...) 9 Code Reuse /Implementation Inheritance: reusing an implementation to create a new class type. Class Clock that inherits from class Window the ability to represent itself graphically. A stack is not really a subtype or specialization of Vector. In this case, inheritance makes implementation easier, because there is no rewrite and debug existing code. This is called using inheritance for reuse, i.e., a pseudo-has-a relation.

10 Functions you don t inherit: constructors and destructors don t inherit and must be created specially for each derived class. However, they may be called automatically where necessary. The operator = doesn t inherited because it performs a constructor-like activity. These functions are synthesized by the compiler if you don t create them yourself.

Upcasting 11 The most important aspect of inheritance is not that it provides member functions for the new class, but the relationship expressed between the new class and the base class. This relationship can be summarized by saying, This new class is a type of the existing class. This description is supported directly by the compiler.

Upcasting (cont ) 12 Inheritance means that all the functions in the base class are also available in the derived class. Thus, any message you can send to the base class can also be sent to the derived class. A pointer to a derived class may always be assigned to a pointer to a base class that was inherited publically (but not vice versa).

Upcasting (cont ) For example, we can now create a list of Employees, some of whom are Managers: void f(employee& emp, Manager& mng) { Employee** emparray = new Employee*[2]; emparray[0] = &emp; emparray[1] = &mng; } Upcasting is safe because you re going from a more specific type to a more general type the only thing that can occur to the class interface is that it can lose member functions, not gain 13 them.

14 Private Inheritance When you inherit privately you re creating a new class that has the data and functionality of the base class, but the functionality is hidden, so it s only part of the underlying implementation. When you inherit privately, all the public members of the base class become private. The class user has no access to the underlying functionality. An object cannot be treated as a instance of the base class. It is illegal to assign the address of a derived object to a pointer to a base object.

Private Inheritance (cont ) 15 Private inheritance or Composition? You ll usually want to use composition rather than private inheritance. Use private inheritance when: you want to produce part of the same interface as the base class and disallow the treatment of the object as if it were a base-class object. In implementation inheritance.

Derived Class Access to Base Class Members Base Class Access Control Inheritance mode public protected private public public protected private protected protected protected private private none none none 16

Inheritance and Assignment operator 17 Consider we have class Base and class Derived (that derived publically from Base). Consider we declare two objects of Derived: Derived d1, d2; And now we want to do: d1 = d2; If the derived class didn't implement the operator=, than the Base's operator= is called. If the derived class did implement the operator=, than only this operator is called.

18 Inheritance and Assignment operator (cont...) If we want also to activate the Base's assignment operator, we need to call it explicitly: class Derived : public Base { //... public: //... Derived& operator=(const Derived& d) { //call the Base version of operator =: Base::operator=(d); //do the assignment concerning the //Derived's attributes. } };

The danger of Implementation Inheritance 19 Using inheritance for reuse may sometimes be a dangerous misuse of the technique. Operations that are valid for the base type may not appeal to the derived type at all. e.g., Stack that inherits class Vector: the operator[ ] is valid for the Vector, not to the Stack. Thus, you can use private base class or use composition instead.

Inheritance vs. Composition White-box Black-box Can change parent s behavior Dependency on parent s implementation Parent defined at compiletime Straightforward Uses polymorphism Parent s behavior is fixed Dependency on parent s interface Parent can be defined at run-time Requires work Uses delegation * Favor object composition over class inheritance *

Example Profiling a HashSet Assume we have the following Map<E> API functions: boolean add(e o) boolean addall(collection<? extends E> c) One implementing class is HashSet<E>. We would like to add a profiling function: int getaddcount() This function returns the number of attempted element insertions

Using Inheritance import java.util.*; public class InstrumentedHashSet extends HashSet{ //The number of attempted element insertions private int addcount = 0; public InstrumentedHashSet() {} public InstrumentedHashSet(Collection c) { super(c); } public InstrumentedHashSet(int initcap, float loadfactor) { super(initcap, loadfactor); }

Using Inheritance Handling Counts public boolean add(object o) { addcount++; return super.add(o); } public boolean addall(collection c) { addcount += c.size(); return super.addall(c); } public int getaddcount() { return addcount; }

Using Inheritance Results What is the result of the following code? public static void main(string[] args) { InstrumentedHashSet s = new InstrumentedHashSet(); s.addall(arrays.aslist( new String[]{"Snap","Crackle","Pop"})); System.out.println(s.getAddCount()); }

Unfortunately the answer is 6 The reason: addall uses add

Possible Solutions Do not override addall: Problem: depends on implementation details Write addall using iteration and add. Cons: Complete re-implementation of the method Sometimes requires access to private members Another problem with previous solutions: What if a different add function is add to HashSet? Another alternative: Composition

Using Composition import java.util.*; public class InstrumentedSet implements Set { private final Set _s; private int _addcount = 0; public InstrumentedSet(Set s) {this._s = s;} public boolean add(object o) { _addcount++; return _s.add(o); } public boolean addall(collection c) { _addcount += c.size(); return _s.addall(c); } public int getaddcount() {return _addcount; }

Forwarding Methods public void clear() { _s.clear(); } public boolean contains(object o) { return _s.contains(o); } public boolean isempty() { return _s.isempty(); } public int size() { return s.size(); } A forwarding method is a method in public Iterator iterator() the wrapper class which invokes { return the corresponding s.iterator(); method in the } public boolean remove(object contained class o) and returns the { return s.remove(o); result } public boolean containsall(collection c) { return _s.containsall(c); }

Forwarding Methods - cont public boolean removeall(collection c) { return _s.removeall(c); } public boolean retainall(collection c) { return _s.retainall(c); } public Object[] toarray() { return _s.toarray(); } public Object[] toarray(object[] a) { return _s.toarray(a); } public boolean equals(object o) { return _s.equals(o); } public int hashcode() { return _s.hashcode(); } public String tostring() { return _s.tostring(); }

The Pros and Cons of Composition Pros for composition The underlying Set is completely encapsulated while inheritance breaks encapsulation Robust, not implementation dependent Flexible, the profiling functionality works with any kind of set

The Pros and Cons of Composition (Cont...) Pros for inheritance Only methods concerned with new functionality need to be overridden Natural choice for some is-a relations (e.g. Strategy, and Composite patterns) Use common sense to weigh the tradeoffs

Liabilities of Multiple Inheritance 32 A base class may legally appear only once in a derivation list. e.g., class A : public B, public B is an error. A base class may appear multiple times within a derivation hierarchy. Can cause method and data member ambiguity. Causes unnecessary duplication of storage.

33 Function name hiding & overriding When you inherit a class and provide a new definition for one of its member functions, If you change the member function argument list or return type in the derived class, all the other versions are automatically hidden in the new class. When you inherit a class and provide a new definition for one of its member functions, If you provide the exact signature and return type in the derived class definition as in the base class definition, we call it redefinition or overriding.

class A { public: void f(int i) {cout<<"a::f(int)";} float* g() {return NULL;} }; class B : public A { public: void f(int i, int j) {cout<<"b::f(int,int)";} int* g() {return NULL;} }; int main() { B b; b.f(2); //error: function does not take 1 parameters float* pf = b.g(); //error: can t convert int* to float* return 0; } 34

Virtual Inheritance 35 Base private: int m_i; public: void f(); Derived_1 Derived_2 Derived_12 With virtual inheritance there is only one copy of each object even if (because of multiple inheritance) the object appears more than once in the hierarchy. class Derived_12 : virtual public Derived_1, virtual public Derived_2 { };

36 Constructors and virtual inheritance class V{ public: V(const char* s) {cout<<s;} }; What will be printed? class B1 : public virtual V{ public: B1(const char* s):v("b1") {cout<<s;} }; class B2 : public virtual V{ public: B2(const char* s):v("b2") {cout<<s;} }; class D : public B1, public B2{ public: D():B1("DB1"),B2("DB2"){} };

Constructors and virtual inheritance (Cont ) 37 Answer: Compilation Error. Solutions: Declare a default constructor in V. Call V s constructor directly from D s: Virtual bases are initialized by the initializer of the most derived class, other initializers are ignored. Virtual bases may be initialized in a constructor of a derived class even if they are not immediate base classes.

Polymorphism

Shape Triangle Rectangle Circle void main( ) Shape* p = GetShape( ); p->draw( ); Shape* GetShape( ) choose randomly which shape to send back Shape* p = some random shape return p; 39

40 Circle Shape* ps Circle* pc Shape::Draw Shape::Rotate Shape::Resize Circle::Draw Circle::Rotate Circle::Resize

41 Binding Time Connecting a function call to a function body is call binding. The problem: at compilation time the compilers attaches the Draw method with the Shape* pointer and calls Shape::Draw() instead of the right method. The cause: in compilation time the compiler doesn t know that Shape* points to a derived class. This information is available only at run time. The solution: postponed the binding between the function call and the exact method to the run time.

42 Dynamic Binding When binding is performed before the program is run (=by the compiler and linker), it s called early binding or static binding. When binding occurs at runtime, it called late binding or dynamic binding. The keyword virtual tells the compiler it should not perform early binding. Instead, it should automatically install all the mechanisms necessary to perform late binding. This means that if you call a Derived class s method through an address for the base-class pointer, you ll get the proper function.

43 Virtual Functions If a function is declared as virtual in the base class, it is virtual in all the derived classes. All derived-class functions that match the signature of the baseclass declaration will be called using the virtual mechanism. The redefinition of a virtual function in a derived class is usually called overriding. Virtual functions must be class methods. Late binding occurs only with virtual functions, and only when you re using an address of the base class where those virtual functions exist, although they may also be defined in an earlier base class.

Virtual Functions (cont...) 44 Virtual methods allow the programmer to declare functions in a base class that can be redefined in each derived class. The compiler and loader will guarantee the correct binding between objects and the functions applied to them. Virtual methods are dynamically bound and dispatched at run-time, using an index into an array of pointers to class methods. The overhead is constant: the VPTR pointer.

45 How does C++ implement late binding? For each class that contains virtual functions the compiler build a table, called virtual table (VTABLE). The compiler places the address of the virtual functions for that particular class in the VTABLE. In each class with virtual functions, it secretly places a pointer, called the vpointer (VPTR), which points to the VTABLE for that object. When a constructor is called, one of the first things is does is initialize its VPTR. However, it can only know that it is of the current type the type the constructor was written for.

46 How does C++ implement late binding? (cont...) class Base { private: int m_x; public: void f1(); virtual void print(); virtual void v(); }; class Derived : public Base { private: int m_y; public: virtual void f2(); void print(); }; int main() { } Base b; Derived d; d.print(); Base* pbase = &b; pbase->print(); pbase = &d; pbase->print(); return 0;

How does C++ implement late binding? (cont...) Building Base s VTAble: b pbase m_x Base virtual table Base::print VPTR Building Derived s VTAble: Step 1: The compiler copies the base s Vtable as is: Base::v Derived virtual table Base ::print Base::v 47

How does C++ implement late binding? (cont...) pbase b m_x VPTR Base virtual table Base::print Base::v Building Derived s VTAble: Step 2: Add additional virtual functions at the end: Derived virtual table Base::print Base::v Derived: f2 48

How does C++ implement late binding? (cont...) pbase b m_x VPTR Base virtual table Base::print Base::v Building Derived s VTAble: 49 Step 3: If Derived overridded virtual functions, change the pointer in the Vtable to reference the new version: Derived virtual table Derived::print Base::v Derived: f2

How does C++ implement late binding? (cont...) The Derived s Constructor changes the pointer to point the Derived Vtable: The Base s Constructor added a pointer to the Base Vtable: d Base::m_x VPTR m_y Base virtual table Base::print Base::v Derived virtual table Derived::print Base::v Derived: f2 50

How does C++ implement late binding? (cont...) pbase b m_x VPTR Base virtual table Base::print Base::v pbase d Base::m_x VPTR m_y Derived virtual table Derived::print Base::v Derived::f2 51

52 what happens when you inherit and add new virtual functions in the derived class? class Base { public: virtual void f_b1(); virtual void f_b2(); }; class Derived : public Base { public: virtual void f_b2(); virtual void f_d(); }; & Base::f_b1 & Base::f_b2 & Base::f_b1 & Derived::f_b2 & Derived::f_d The compiler maps the location of f_b1() address into exactly the same spot in Derived VTABLE as it is in the Base VTABLE. Since the compiler is working only with a pointer to a baseclass object, the only functions that the compiler allows to call through this pointer are the base s methods. The compiler protects you from making virtual calls to functions that exist only in derived classes.

How does C++ implement late binding? (cont...) class NoVirtual { int m_a; public: void f(){} }; class YesVirtual { int m_a; public: virtual void f(){} }; void main() { cout<<"int : "<<sizeof(int)<<endl; cout<<"novirtual: "<<sizeof(novirtual)<<endl; cout<<"yesvirtual:"<<sizeof(yesvirtual)<<endl; } 53

How does C++ implement late binding? (cont...) When the compiler generates code for a constructor, it generates code for a constructor of that class, not a base class and not a class derived from it (because a class can t know who inherits it). So the VPTR it uses must be for the VTABLE of that class. The VPTR remains initialized to that VTABLE for the rest of the object s lifetime, unless this isn t the last constructor call. The state of the VPTR is determine by the constructor that is called last. (QUIZ: what happens when we call a virtual function from a constructor? and from a destructor?) 54

Why virtual functions? 55 If this technique is so important, and if it makes the right function call all the time, why is it an option? Why do I even need to know about it? Efficiency: time & space. inline functions: virtual functions must have an address to put into the VTABLE. If you don t use it, you don t pay for it (Stroustrup). Some object oriented languages (Smalltalk, Java, Python, etc.) have taken the approach that late binding is so intrinsic to object-oriented programming that it should always take place.

56 Abstract classes and pure virtual functions We want the base class to present only an interface for its derived classes. class Employee had a meaning and also the derived class Manager. However, class Shape has no meaning only its derived classes. In this case, we don t want anyone to actually create an object of the base class, only to upcast to it so that its interface can be used. If you declare at least one pure virtual function inside a class, this class becomes an abstract class. You can recognize a pure virtual function because it uses the virtual keyword and is followed by =0.

Abstract classes and pure virtual functions (cont...) You cannot create any instances from an abstract class. Note that pure virtual functions prevent an abstract class from being passed into a function by value. When an abstract class is inherited, all pure virtual functions must be implemented, or the inherited class becomes abstract as well. You create an abstract class when you only want to manipulate a set of classes through a common interface, but the common interface doesn t need to have an implementation (or at least, a full implementation). 57

Abstract classes and pure virtual functions (cont...) Shape virtual void draw() = 0; virtual void rotate(float) = 0; virtual void enlarge(float) = 0; virtual int perimeter() = 0; Polygon int perimeter(){ } 58 Rectangle void draw() { }; void rotate(float) { }; void enlarge(float) { }; Circle void draw() { }; void rotate(float) { }; void enlarge(float) { }; int perimeter(){ }

Virtual Destructor 59 pbase BASE DERIVED HEAP

Virtual Destructor (cont ) Assume you want to delete a pointer of a derived type for an object that has been created on the heap with new. If the pointer is to the base-class, the compiler can only know to call the base-class version of the destructor during delete. Problem: we want to call the destructor of the derived class, if it has memory allocation in it. Sounds familiar? This is the same problem that virtual functions were created to solve for the general case. Solution: declare the destructor as virtual. 60

Dynamic vs. static binding We use static binding when: we are sure that any subsequent derived classes will not want to override this operation dynamically (just redefine/hide). we reuse code or form a concrete data types. We use dynamic binding when: 61 the derived classes may be able to provide a different (more functional, more efficient) implementation that should be selected at run-time. we build dynamic type hierarchies and form an abstract data type.

Dynamic vs. static binding (cont...) 62 Static binding is more efficient than dynamic binding. It has less time and space overhead. Enable inline functions. Dynamic binding is more flexible than static binding. Enables developers to extend the behavior of a system transparently.

63 object slicing BASE TYPE BASE TYPE DERIVED TYPE

64 object slicing (cont...) There is a distinct difference between passing addresses and passing values when treating objects polymorphically. addresses all have the same size, so passing the address of an object of a derived type (which is usually bigger) is the same as passing the address of an object of the base type (which is usually smaller). If you use an object instead of a pointer or reference as the recipient of your upcast, the object is sliced until all that remains is the subobject that corresponds to your destination.

65 object slicing (cont...) When passing a derived object by value, the compiler knows the precise type of the object because the derived object has been forced to become a base object. When passing by value, the copy-constructor for the base class is used, which initializes the VPTR to the base s VTABLE and copies only the base s parts of the object. You can explicitly prevent object slicing by putting pure virtual functions in the base class; this will cause a compile-time error message for an object slice.

Downcasting and RTTI 66 Upcasting is easy: as you move up an inheritance hierarchy the classes always converge to more general (and usually smaller) classes. usually there is one ancestor class. The compiler does the casting for you: Base* pb = new Derived; However, when you downcast there is usually more than one derived classes you could cast to. a Circle is a type of Shape (that s the upcast), but if you try to downcast a Shape it could be a Circle, Square, Triangle, etc.

67 Downcasting is the term used in C++ for casting a pointer or reference to a base class to a derived class. You CANNOT do the following: RTTI (cont...) Derived* d = new Base; It is not safe to do: Circle *pc = (Circle*)pShape; C++ provides a special explicit cast for type-safe downcast operations. This mechanism is called Run-Time Type Information (RTTI). Necessary since C++ originally didn t support overloading on function return type.

68 RTTI (cont...) There are two different ways to use RTTI. typeid( ) - takes an argument that s an object, a reference, or a pointer and returns a reference to a global const object of type typeinfo. It s implemented by the compiler. You can also ask for the name( ) of the type, which returns a string representation of the type name.

RTTI (cont...) type-safe downcast - The dynamic_cast operator returns a valid pointer if the object is of the expected derived type otherwise it returns a null pointer. The syntax looks like: Derived *d_ptr = dynamic_cast<derived*> (ptr); This will result into an assignment if the object pointed to by ptr is of type Derived, otherwise d_ptr will become equal to NULL.

70 RTTI (cont...) As opposed to typeid, a dynamic_cast isn't a constant time operation. In order to determine whether the cast can be performed, dynamic_cast must traverse the derivation lattice of its argument at runtime. Therefore, use dynamic_cast judiciously. TIP: Certain compilers, such as Visual C++, disable RTTI by default to eliminate performance overhead. If your program does use RTTI, remember to enable RTTI before compilation.

RTTI example 1: 71 class Pet { public: virtual ~Pet(){} }; class Dog : public Pet {}; class Cat : public Pet {}; void main() { Pet* b = new Cat; // Upcast // Try to cast it to Dog*: Dog* d1 = dynamic_cast<dog*>(b); // Try to cast it to Cat*: Cat* d2 = dynamic_cast<cat*>(b); cout << "d1 = " << (long)d1 << endl; cout << "d2 = " << (long)d2 << endl; } RTTI (cont...)

72 RTTI example 2: class IFile { public: virtual int open(const string& filename)=0; virtual int close(const string& filename)=0; //... virtual ~File()=0; // remember to add a pure virtual dtor };

class DiskFile: public IFile { public: 73 }; int open(const string & filename); //...implementation of other pure virtual functions // specialized operations... virtual int flush(); virtual int defragment(); IFile class TextFile: public DiskFile { //... int sort_by_words(); }; class MediaFile: public DiskFile { //... }; TextFile DiskFile MediaFile

RTTI example (cont...) 74 IFile* FileFactory(string condition) { IFile *pfile=null; //static type of *pfile is File if(analyzecondition(condition))==text) pfile = new TextFile;//dynamic type is TextFile else if analyzecondition(condition))==disk) pfile = new DiskFile;//dynamic type is DiskFile else //... } return pfile;

RTTI (cont...) 75 Suppose you're developing a GUI-based file manager that displays files as icons. When you pass your mouse over such an icon and click, the file manager opens a menu that adjusts itself dynamically according to the marked file. The menu lists a set of operations such as "copy", "paste," and "open." In addition, it displays specialized operations for the particular file. Thus, for a text file, it adds the "edit" operation whereas for a multimedia file it displays the "play" operation instead. To customize the menu dynamically, the file manager has to probe each files dynamic type.

RTTI example (cont...) 76 #include <typeinfo> // needed for typeid //using typeid void Menu::Build(const IFile* pfile) { if (typeid(*pfile)==typeid(textfile)) { add_option("edit"); } else if (typeid(*pfile)==typeid(mediafile)) { add_option("play"); } }

RTTI example (cont...) 77 //the same but using dynamic_cast void Menu::Build(const IFile * pfile) { if (dynamic_cast <MediaFile *> (pfile)) { // pfile is MediaFile or LocalizedMedia add_option("play"); } else if (dynamic_cast <TextFile*> (pfile)) { // pfile is a TextFile or a class derived from it add_option("edit"); } }

Implicit conversion Implicit conversions are automatically performed by the compiler when a value is copied to a compatible type. In a mixed-type expression, data of one or more subtypes can be converted to a supertype as needed at runtime so that the program will run correctly. Type Promotion = where the compiler automatically expands the binary representation of objects of integer or floating-point types.

Explicit type conversion Type conversion which is explicitly defined within a program (instead of being done by a compiler for implicit type conversion). Checked = Before the conversion is performed, a runtime check is done to see if the destination type can hold the source value. If not, an error condition is raised. Unchecked = No check is performed. If the destination type cannot hold the source value, the result is undefined. bit pattern = The raw bit representation of the source is copied verbatim, and it is re-interpreted according to the destination type. This can also be achieved via aliasing.

Specific type casts A set of casting operators have been introduced into the C++ language to address the shortcomings of the old C- style casts, maintained for compatibility purposes. Bringing with them a clearer syntax, improved semantics and type-safe conversions. static_cast - static_cast<target type>(expression) The compiler will try its best to interpret the expression as if it would be of type type. This type of cast will not produce a warning, even if the type is demoted. Cannot cast const to non-const, and it cannot perform "crosscasts" within a class hierarchy.

Specific type casts (Cont ) dynamic_cast = static_cast<target type>(expression) The type-id must be a pointer or a reference to a previously defined class type or a "pointer to void". The type of expression must be a pointer if type-id is a pointer, or an l- value if type-id is a reference.

The 'static_cast operator static_cast<type>(expression) Works where implicit conversion exists standard or user-defined conversion up-casts Safer that old-style casts e.g. won t cast int* to float* Failure causes a compiler error No dynamic checking is done! int i = static_cast<int>(12.45);

The const_cast operator const_cast<type>(expression) Is used to remove (or add) const-ness: void g(c * cp); void f(c const* cp) { g(const_cast<c *>(cp)); } Usually, you should design your variables/methods such that you won t have to use const_cast. Failure causes compiler errors

reinterpret_cast operator Is used to reinterpret byte patterns. double d(10.2); char* dbytes = reinterpret_cast<char *>(&d); Circumvents the type checking of c++. Very implementation-dependent. reinterpret_cast<type>(expression) Rarely used. Very dangerous!

Specific type casts (Cont ) In general you use static_cast when you want to convert numeric data types such as enums to ints or ints to floats, and you are certain of the data types involved in the conversion. static_cast conversions are not as safe as dynamic_cast conversions, because static_cast does no run-time type check, while dynamic_cast does. A dynamic_cast to an ambiguous pointer will fail, while a static_cast returns as if nothing were wrong; this can be dangerous. Although dynamic_cast conversions are safer, dynamic_cast only works on pointers or references, and the run-time type check is an overhead.

RTTI (cont...) 86 RTTI and OOP Object-oriented pundits claim that with a proper design and judicious use of virtual member function, you won't need to use RTTI. However, under certain conditions, dynamic type detection is sometimes unavoidable.