0% found this document useful (0 votes)
247 views

01-Polymorphism - Virtual Functions

Here, only the base class destructor is called. To ensure the derived class destructor is called, the base class destructor needs to be declared virtual.
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
247 views

01-Polymorphism - Virtual Functions

Here, only the base class destructor is called. To ensure the derived class destructor is called, the base class destructor needs to be declared virtual.
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 24

DYNAMIC POLYMORPHISM

1 Virtual Functions
OBJECTIVES
 Polymorphism in C++
 Pointers to derived classes
 Important point on inheritance
 Introduction to virtual functions
 Virtual destructors
 More about virtual functions
 Final comments
 Applying polymorphism

2
BINDING
 Connecting a function call to a function body is
called binding
 When a function is called, which function
definition to invoke, when there are more than
one definitions
 Types of binding
 Static or Early binding
 Dynamic or Late binding

3
POLYMORPHISM IN C++
 2 types
 Compile time polymorphism
 Uses static or early binding
 Example: Function, Operator overloading and Templates

 Run time polymorphism


 Uses dynamic or late binding
 Example: Virtual functions

4
POINTERS TO DERIVED CLASSES
 C++ allows base class pointers to point to
derived class objects.
 Let we have –
 class base { … };
 class derived : public base { … };

 Then we can write –


 base *p1; derived d_obj; p1 = &d_obj;
 base *p2 = new derived;

5
POINTERS TO DERIVED
CLASSES (CONTD.)
 Using a base class pointer (pointing
to a derived class object) we can
access only those members of the
derived object that were inherited
from the base.
 This is because the base pointer
has knowledge only of the base class.
 It knows nothing about the members
added by the derived class.

6
POINTERS TO DERIVED
CLASSES (CONTD.)
 class base {  void main() {
 public:  base b1;
 void show() {  b1.show(); // base
 cout << “base\n”;  derived d1;
 }  d1.show(); // derived
 };  base *pb = &b1;
 class derived : public base {  pb->show(); // base
 public:  pb = &d1;
 void show() {  pb->show(); // base
 cout << “derived\n”;  }
 }  All the function calls here
 }; are statically bound

Show Code 7
POINTERS TO DERIVED CLASSES
(CONTD.) - SOLUTION
 class base {  void main() {
 public:  base b1;
 virtual void show() {  b1.show(); // base - (s.b.)
 cout << “base\n”;  derived d1;
 }  d1.show(); // derived – (s.b.)
 };  base *pb = &b1;
 class derived : public base {  pb->show(); // base - (d.b.)
 public:  pb = &d1;
 void show() {  pb->show(); // derived
(d.b.)
 cout << “derived\n”;
 }
 }
Show Code
 };
 Here, 8
 s.b. = static binding
 d.b. = dynamic binding
POINTERS TO DERIVED
CLASSES (CONTD.)
 Whileit is permissible for a base class
pointer to point to a derived object, the
reverse is not true.
 base b1;
 derived *pd = &b1; // compiler error
 We can perform a downcast with the
help of type-casting, but should use it
with caution ( see next )

9
POINTERS TO DERIVED
CLASSES (CONTD.)

 Let we have –
class base { … };
class derived : public base { … };
class xyz { … }; // having no relation with “base” or “derived”
 Then if we write –
1. base b_obj; base *pb; derived d_obj; pb = &d_obj; // ok
2. derived *pd = pb; // compiler error
3. derived *pd = (derived *)pb; // ok, valid downcasting
4. xyz obj; // ok
5. pd = (derived *)&obj; // invalid casting, no compiler error, but
may cause run-time error
6. pd = (derived *)&b_obj; // invalid casting, no compiler error,
but may cause run-time error
10
POINTERS TO DERIVED
CLASSES (CONTD.)

 Infact using type-casting, we can use pointer


of any class to point to an object of any other
class.
 The compiler will not complain.
 During run-time, the address assignment will also
succeed.
 But if we use the pointer to access any member,
then it may cause run-time error.
 Java prevents such problems by throwing
“ClassCastException” in case of invalid 11

casting.
POINTERS TO DERIVED
CLASSES (CONTD.)

 Pointer arithmetic is relative to the data type


the pointer is declared as pointing to.
 If we point a base pointer to a derived object
and then increment the pointer, it will not be
pointing to the next derived object.
 It will be pointing to the next base object !!!

 Be careful about this.

12
IMPORTANT POINT ON
INHERITANCE
 In C++, only public inheritance supports the perfect
IS-A relationship.
 In case of private and protected inheritance, we cannot
treat a derived class object in the same way as a base
class object
 Public members of the base class becomes private or protected
in the derived class and hence cannot be accessed directly by
others using derived class objects
 If we use private or protected inheritance, we cannot
assign the address of a derived class object to a base
class pointer directly.
 We can use type-casting, but it makes the program logic and
structure complicated.
 This is one of the reason for which Java only supports
public inheritance. 13
INTRODUCTION TO VIRTUAL
FUNCTIONS
A virtual function is a member function
that is declared within a base class and
redefined by a derived class.
 The redefinition of a virtual function in a
derived class is usually called overriding.
 It implements the “one interface, multiple
methods” philosophy that underlies
polymorphism.
 The keyword virtual is used to designate
a member function as virtual.
 Supports run-time polymorphism with the
help of base class pointers. 14
INTRODUCTION TO VIRTUAL
FUNCTIONS (CONTD.)
 While redefining a virtual function in a
derived class, the function signature must
match the original function present in the
base class.
 So, we call it overriding, not overloading.
 When a virtual function is redefined by a
derived class, the keyword virtual is not
needed (but can be specified if the
programmer wants).
 The “virtual”-ity of the member function
continues along the inheritance chain.
 A class that contains a virtual function is 15
referred to as a polymorphic class.
INTRODUCTION TO VIRTUAL
FUNCTIONS (CONTD.)

 class base {  void main() {


 public:  base b1;
 virtual void show() {  b1.show(); // base - (s.b.)
 cout << “base\n”;  derived d1;
 }  d1.show(); // derived – (s.b.)
 };  base *pb = &b1;
 class derived : public base {  pb->show(); // base - (d.b.)
 public:  pb = &d1;
 void show() {  pb->show(); // derived
(d.b.)
 cout << “derived\n”;
 }
 }
 Here,
 }; 16
 s.b. = static binding
 d.b. = dynamic binding
INTRODUCTION TO VIRTUAL
FUNCTIONS (CONTD.)

 class base {  class d2 : public base {


 public:  public:
 virtual void show() {  void show() {
 cout << “base\n”;  cout << “derived-2\n”;
 }  }
 };  };
 class d1 : public base {  void main() {
 public:  base *pb; d1 od1; d2 od2;
 void show() {  int n;
 cout << “derived-1\n”;  cin >> n;
 }  if (n < 2) pb = &od1;
 };  else pb = &od2;
 pb->show(); // guess what ??
17
Run-time polymorphism  }
VIRTUAL DESTRUCTORS
 Constructors cannot be virtual, but destructors
can be virtual.
 It ensures that the derived class destructor is
called when a base class pointer is used while
deleting a dynamically created derived class
object.

18
VIRTUAL DESTRUCTORS (CONTD.)

 class base {  void main() {


 public:  base *p = new derived;
 ~base() {  delete p;
 cout << “destructing base\n”;  }
 }
 };  Output:
 class derived : public base {  destructing base
 public:
 ~derived() {
 cout << “destructing derived\n”;
 }
 };

19
Using non-virtual destructor
VIRTUAL DESTRUCTORS (CONTD.)

 class base {  void main() {


 public:  base *p = new derived;
 virtual ~base() {  delete p;
 cout << “destructing base\n”;  }
 }
 };  Output:
 class derived : public base {  destructing derived
 destructing base
 public:
 ~derived() {
 cout << “destructing derived\n”;
 }
 };

20
Using virtual destructor
MORE ABOUT VIRTUAL FUNCTIONS
 Ifwe can omit the body of a virtual
function in a base class, we can use pure
virtual functions.
virtual ret-type func_name(param-list) = 0;
 It makes a class an abstract class.
 We cannot create any objects of such classes.
 It forces derived classes to override it.
 Otherwise they become abstract too.

21
MORE ABOUT VIRTUAL
FUNCTIONS (CONTD.)
 Pure virtual function
 Helps to guarantee that a derived class will
provide its own redefinition.
 We can still create a pointer to an abstract
class
 Because it is at the heart of run-time
polymorphism
 When a virtual function is inherited, so it
is virtual nature.
 We can continue to override virtual
functions along the inheritance hierarchy. 22
FINAL COMMENTS
 Classes from which objects can be instantiated are
called concrete classes.
 If a class has nothing but pure virtual functions, we
call it a pure abstract class
 Run-time polymorphism is not automatically activated
in C++.
 We have to use virtual functions and base class
pointers to enforce and activate run-time
polymorphism in C++.
 But, in Java, run-time polymorphism is automatically
present as all non-static methods of a class are by
default virtual in nature.
 We just need to use superclass references to point to subclass
objects to achieve run-time polymorphism in Java. 23
APPLYING POLYMORPHISM
 Early binding
 Normal functions, overloaded functions
 Nonvirtual member and friend functions, Even
Templates also.
 Resolved at compile time
 Very efficient
 But lacks flexibility
 Late binding
 Virtual functions accessed via a base class pointer
 Resolved at run-time
 Quite flexible during run-time
 But has run-time overhead; slows down program
execution
24

You might also like