Skip to main content
CSC103 - Object Oriented
         Programming

             Lecture 19

          Engr. M. Anwar-ul-Haq

             11th May, 2011

Foundation University (FUIEMS), Islamabad
Engr. Anwar, Foundation University (FUIEMS), Islamabad   2
Virtual Functions
                       Function Call Binding
•       Connecting a function call to a function body is called
        binding.
•       When binding is performed before the program is run
        (by the compiler and linker), it is called early or static
        binding.
•       When the binding is performed at runtime, based on
        the object type, it is called late, dynamic or runtime
        binding.
    –     To perform late binding, the language must provide some
          mechanism through which late binding could be achieved.
    –     In C++, late binding is achieved through the use of virtual
          functions and base class pointer (or reference) to point to the
          derived class object.
                 Engr. Anwar, Foundation University (FUIEMS), Islamabad   3
Virtual Functions
     Normal Member Functions Accessed with Pointers
#include <iostream>
using namespace std;

class Base {
public:
       void show() { cout << "nBase Classn";}
};

class Derv1 : public Base {
public:
       void show() { cout << "nDerived class 1n"; }
};

class Derv2 : public Base {
public:
       void show() { cout << "nDerived class 2n"; }
};


              Engr. Anwar, Foundation University (FUIEMS), Islamabad   4
Virtual Functions
     Normal Member Functions Accessed with Pointers
void main() {
       Derv1 dv1;     // object of derived class 1
       Derv2 dv2;     // object of derived class 2

      dv1.show(); // will display Derived class 1
      dv2.show(); // will display Derived class 2

      // Let's do the same with pointers
      Base* ptr;          // declare a pointer to the base class

      ptr = &dv1;                     // put address of dv1 in pointer
      ptr->show();                    // execute show(), displays Base Class

      ptr = &dv2;                     // put address of dv2 in pointer
      ptr->show();                    // execute show(), displays Base Class
}


              Engr. Anwar, Foundation University (FUIEMS), Islamabad   5
Virtual Functions
    Normal Member Functions Accessed with Pointers
•   Refer to the program given in the last two slides. The Derv1 and
    Derv2 classes are derived from class Base. Each of these classes
    has a member function show().
•   In main, we create objects of class Derv1 and Derv2, and a
    pointer to the class Base.
•   We then put the address of a derived class object in the base
    class pointer. This is possible because pointers to objects of a
    derived class are type compatible with pointers to objects of the
    base class.
•   However, we note by executing the program, that when the
    statement ptr->show() is executed, the show () function in the
    base class is executed.
•   The compiler ignores the contents of the pointer ptr and chooses
    the member function that matches with the type of the pointer
              Engr. Anwar, Foundation University (FUIEMS), Islamabad   6
Virtual Functions
     Virtual Member Functions Accessed with Pointers
#include <iostream>
using namespace std;

class Base {
public:
       virtual void show() { cout << "nBasen";}
};

class Derv1 : public Base {
public:
       void show() { cout << "nDerived class 1n"; }
};

class Derv2 : public Base {
public:
       void show() { cout << "nDerived class 2n"; }
};


              Engr. Anwar, Foundation University (FUIEMS), Islamabad   7
Virtual Functions
     Virtual Member Functions Accessed with Pointers
void main() {
       Derv1 dv1;     // object of derived class 1
       Derv2 dv2;     // object of derived class 2

      dv1.show(); // will display Derived class 1
      dv2.show(); // will display Derived class 2

      // Let's do the same with pointers
      Base* ptr;          // declare a pointer to the base class

      ptr = &dv1;                     // put address of dv1 in pointer
      ptr->show();                    // displays Derived class 1

      ptr = &dv2;                     // put address of dv2 in pointer
      ptr->show();                    // displays Derived class 2
}


              Engr. Anwar, Foundation University (FUIEMS), Islamabad     8
Virtual Functions
    Virtual Member Functions Accessed with Pointers
•   Refer to the program given in the last two slides.
•   In this case, the member functions of the derived class, not the
    base class, are executed.
•   The same functions call ptr->show(); executes different functions,
    depending on the contents of ptr.
•   Thus the compiler selects the function based on the contents of
    the pointer ptr, not on the type of the pointer.
•   In this particular case, the compiler doesn’t know what class the
    contents of ptr may contain. It defers the decision until the
    program is running.
•   At runtime, when it is known what class is pointed to by ptr, the
    appropriate version of draw() is called.
•   This is late binding or dynamic binding.
              Engr. Anwar, Foundation University (FUIEMS), Islamabad   9
Abstract Base Classes and
                     Concrete Classes
•       An abstract class is often defined as one that will not be
        used to create any objects, but exists only to act as a
        base class of other classes.
    –     Since these classes are used as base classes in inheritance
          situations, we normally refer to them as abstract base classes.
•       Classes from which objects can be instantiated are
        called concrete classes.
•       A class is made abstract by declaring one or more its
        virtual functions to be “pure”.
    –     A pure virtual function is one with an initializer of =0 in its
          declaration, e.g.
                 virtual void show() = 0; // pure virtual function

                  Engr. Anwar, Foundation University (FUIEMS), Islamabad    10
Abstract Base Classes and
               Concrete Classes …
•   If a class is derived from a class with a pure virtual
    function, and if no definition is supplied for that pure
    virtual function in the derived class, then that virtual
    function remains pure in the derived class.
    Consequently, the derived class is also an abstract class.
•   Attempting to instantiate an object of an abstract class
    (i.e. a class that contains one or more pure virtual
    functions) is a syntax error.
•   A hierarchy does not need to contain any abstract
    classes, but many good object-oriented systems have
    class hierarchies headed by an abstract class.
•   In some cases, abstract classes constitute the top few
    levels of hierarchy.
             Engr. Anwar, Foundation University (FUIEMS), Islamabad   11
Polymorphism
•       Poly mean many and morph means forms – thus polymorphism
        means to take up many forms.
•       C++ enables polymorphism – the ability for objects of different
        classes related by inheritance to respond differently to the same
        message (i.e. member function call).
    –      For example, if class Rectangle is derived from class Quadrilateral, then
           Rectangle object is more specific version of Quadrilateral object.
    –      An operation (such as calculating the perimeter or area) that can be
           performed on an Quadrilateral object also can be performed on a
           Rectangle object.
•       Polymorphism is implemented via virtual functions.
    –      When a request is made through a base-class pointer (or reference) to use
           a virtual function, C++ chooses the correct overridden function in the
           appropriate derived class associated with the object.


                    Engr. Anwar, Foundation University (FUIEMS), Islamabad        12
Exploiting Inheritance

• What can be done with different classes related by
  inheritance?
   – Any child of a class, can be stored in a pointer to that of
     parent class
• This is called polymorphism




                        Engr. Anwar, Foundation University
                                                                   13
                               (FUIEMS), Islamabad
How does polymorphism work?

• When a base class pointer is used to
  store one of it’s children, any method
  declared in the base class can be called.
• However, any methods that are not
  declared in the base class can not be
  called.



               Engr. Anwar, Foundation University
                                                    14
                      (FUIEMS), Islamabad
How does polymorphism work?
• By default when a function is called using the
  base class pointer, the method called will be
  the one defined in the base class not the child
  being pointed at).
  – This is often not what you want to have happen.




                  Engr. Anwar, Foundation University
                                                       15
                         (FUIEMS), Islamabad
Polymorphism Defined
• The ability to take on different forms.
• Ability for different objects to interpret functions
  differently
• Manipulate objects of various classes, and invoke
  methods on an object without knowing that
  object’s type.




                     Engr. Anwar, Foundation University
                                                          16
                            (FUIEMS), Islamabad
Polymorphism
• - extending inheritance
• Polymorphism means using the same syntax to do
  different things depending on the context
• Polymorphism describes the ability of one operation
  to be called for various objects, which, in turn, may
  react differently.
• In C++ context, this means that different classes can
  react differently for the same function call.



                    Engr. Anwar, Foundation University
                                                         17
                           (FUIEMS), Islamabad
Polymorphism
• Why Is this Important?
  – Allow subclasses to be treated like instances of their
    super classes
  – Flexible architectures and designs
     • high-level logic defined in terms of abstract interfaces
     • relying on the specific implementation provided by
       subclasses
     • subclasses can be added without changing high-level
       logic



                     Engr. Anwar, Foundation University
                                                                  18
                            (FUIEMS), Islamabad
Using Base Class Pointer
class Box
   {
    };
class Carton : public Box
   { };
class Contents
   { };
class CerealPack : public Carton, public Contents
   {

  };
                 Engr. Anwar, Foundation University
                                                      19
                        (FUIEMS), Islamabad
Using Base Class Pointer
CerealPack breakfast;
//You can store the address of the breakfast object in
  any base pointer

Carton * pCarton = &breakfast;
Box * pBox=&breakfast;
Contents* pContents=&breakfast;
// but the reverse is not true

                    Engr. Anwar, Foundation University
                                                         20
                           (FUIEMS), Islamabad
Using Base Class Pointer
class Box
  {
   };
class Carton : public Box
  { };
class ToughPack : public Box
  { };


              Engr. Anwar, Foundation University
                                                   21
                     (FUIEMS), Islamabad
Using Base Class Pointer
Carton acarton(10, 10 , 5);
Box * pBox=&acarton;

ToughPack hardcase(2, 2, 2)
pBox=&hardcase;

• The pointer at the time of its declaration
  is called static type
• It also has a dynamic type, which varies
  according to the type of object it points to.
                 Engr. Anwar, Foundation University
                                                      22
                        (FUIEMS), Islamabad
Polymorphism
• Static and dynamic binding
   – In most programming languages and in most cases the
     variables are bound to a specific type at compile time
      • Static binding
   – Dynamic binding
      • The type of the variable can change at run time
      • Using pointers to classes related by inheritance in C+
        +




                         Engr. Anwar, Foundation University
                                                                 23
                                (FUIEMS), Islamabad
Virtual Functions
• A virtual function is a function that is declared with
  the keyword virtual in a base class and then redefined
  by a derived class.

• When a virtual function is invoked by a base class
  pointer, the type of object being pointed at
  determines which version of the function is called.

• The keyword virtual is only required in the base class,
  but many programmers use it in derived classes
  simply to remind themselves that the function is
  virtual.

                    Engr. Anwar, Foundation University
                                                         24
                           (FUIEMS), Islamabad
Virtual Functions
• Used to support polymorphism with pointers and
  references

• Ensures derived class function definition is resolved
  dynamically

• When you declare as virtual in a base class, you
  indicate to the compiler that you want dynamic
  binding for the function in any class that’s derived
  from this base class



                   Engr. Anwar, Foundation University
                                                         25
                          (FUIEMS), Islamabad
Polymorphism
   Ability to manipulate derived objects using the interface
     defined in the base class
• Example:
   class Employee {
   public:
     void CalcPay ();
   };

   class SalariedEmployee :public Employee{
   public:
     void CalcPay ();
   };



                       Engr. Anwar, Foundation University
                                                               26
                              (FUIEMS), Islamabad
Example
   Employee *ep;
   ep = new SalariedEmployee;
   Ep->CalcPay();

• Which function is called?
  – The function in Employee is called

• To avoid that we have to declare CalcPay() as a virtual
  function



                  Engr. Anwar, Foundation University
                                                        27
                         (FUIEMS), Islamabad
Polymorphism
   Ability to manipulate derived objects using the interface
     defined in the base class
• Example:
   class Employee {
   public:
     virtual void CalcPay ();
   };

   class SalariedEmployee :public Employee{
   public:
     virtual void CalcPay ();
   };



                       Engr. Anwar, Foundation University
                                                               28
                              (FUIEMS), Islamabad
Example
   Employee *ep;
   ep = new SalariedEmployee;
   ep->CalcPay();

• Which function is called?
  – The function in SalariedEmployee is called




                Engr. Anwar, Foundation University
                                                     29
                       (FUIEMS), Islamabad
Example: Virtual Functions

  class Employee {
  public:
    virtual void CalcPay ();
  };
  class SalariedEmployee :public Employee{
  public:
    virtual void CalcPay ();
  };
• virtual specifier needs to appear in the base class
  only.
                  Engr. Anwar, Foundation University
                                                       30
                         (FUIEMS), Islamabad
Examples
Employee *p0 = new Employee;
Employee *p1 = new SalariedEmployee;

p0->CalcPay(); // calls employee::CalcPay()
p1->CalcPay(); // calls SalariedEmployee::CalcPay()




                    Engr. Anwar, Foundation University
                                                         31
                           (FUIEMS), Islamabad
Requirements for Virtual
                Functions
• Not every function can be declared virtual.
• Following functions cannot be virtual
   – Non-member functions,
   – Static member functions,
   – Constructors, and
   – Friend functions cannot be virtual.




                    Engr. Anwar, Foundation University
                                                         32
                           (FUIEMS), Islamabad
Requirements for Virtual
                 Functions
• For a function to behave virtually you must declare
  and define it with the same name and parameter list
  in any derived class as it has in the base class.
• If you have declared the base class function as const,
  then you must declare the derived class function to be
  const as well.
• The return type should also be the same




                   Engr. Anwar, Foundation University
                                                        33
                          (FUIEMS), Islamabad
Requirements for Virtual Functions

• If you try to use different parameters for
  virtual function then the virtual function
  mechanism will not work.
• The function in the derived class will
  operate with static binding.




                  Engr. Anwar, Foundation University
                                                       34
                         (FUIEMS), Islamabad
Combinations of virtual and non-
            virtual functions
• Non-virtual function can call virtual function

   class Employee {
   public:
      void Display() const;
      virtual void CalcPay ();
   };


   class SalariedEmployee : public Employee{
   public:
      void Display() const;
      virtual void CalcPay ();
   };


                        Engr. Anwar, Foundation University
                                                             35
                               (FUIEMS), Islamabad
Example
void Employee::Display()
{ cout<<“pay of emp”;
   CalcPay();
};

void SalariedEmployee::Display()
{
   cout<<“pay of salried emp”;
   CalcPay();
};

Employee *p0 = new SalariedEmployee;
p0->Display();

// calls SalariedEmployee::CalcPay();


                    Engr. Anwar, Foundation University
                                                         36
                           (FUIEMS), Islamabad
Access Specifers in Virtual Functions:
                       Example
class Box{
   public:
        Box();
        void showVolume() const;
        virtual double volume() const;
   public:
                 int length, width, height;
};

void Box::showVolume() const
{
   cout<<“ Box usable volume is” <<volume()<<endl;
}
double Box::volume()
{
   return length* base* height;
}                        Engr. Anwar, Foundation University
                                                              37
                              (FUIEMS), Islamabad
class ToughPack:: public Box{
   public:
        ToughPack();
   protected:
        double volume() const;
};
Double ToughPack : : volume() const
{
   return 0.5* length* base* heigth; }

int main()
{ box mybox;           ToughPack hardcase;
    myBox. volume();
    hardcase.volume();                  //error

    box *pbox=&mybox;
    pbox->volume();
    pbox=&hardcase;
    pbox->volume()                                //correct
                         Engr. Anwar, Foundation University
                                                              38
}                               (FUIEMS), Islamabad
Using References with Virtual
                     Functions
class Biomolecule{
        virtual int Mweight();
        .                                         void printMW(Biomolecule &bm){
        };                                                cout<<“Molecular weight is:”
                                                                 <<bm.Mweight();
class Protein: public Biomolecule {               }
Public:
         int Mweight();                           int main( ){
         .                                                Protein p;
};                                                        DNA d;
                                                          .
class DNA : public Biomolecule{                           .
Public:                                                   .
        int Mweight();                                    printMW(p);
};                                                        printMW(d);
                                                  }

                              Engr. Anwar, Foundation University
                                                                                 39
                                     (FUIEMS), Islamabad
Polymorphism vs. Inheritance
• Inheritance is required in order to achieve
  polymorphism (we must have class hierarchies).
   – Re-using class definitions via extension and redefinition


• Polymorphism is not required in order to achieve
  inheritance.
   – An object of class A acts as an object of class B (an
     ancestor to A).




                     Engr. Anwar, Foundation University
                                                             40
                            (FUIEMS), Islamabad
Virtual functions
  • Function of derived class is called even if you have
    only a pointer to the base class
                                    File.cpp
File.h
                                    void Func1()
class Shape
                                    {
{
                                      Circle mycirc;
   virtual void Draw();
                                      Func2(&mycirc);
};
                                    }
class Circle : public Shape
                                    void Func2(Shape* s)
{
                                    {
   virtual void Draw();
                                      s->Draw();
};
                                    }


                                                           // calls Circle::Draw()
                      Engr. Anwar, Foundation University
                                                                             41
                             (FUIEMS), Islamabad
How a virtual function works
Shape vtable                                        Circle vtable
vfunc1 addr                                         vfunc1 addr
vfunc2 addr                                         vfunc2 addr
    ...                                                 ...
vfuncN addr                                         vfuncN addr


                     mycirc
                        var1
                         ...
                        varM
                 vtable ptr
               Engr. Anwar, Foundation University
                                                                    42
                      (FUIEMS), Islamabad
What is the penalty of a virtual
              function?
• Space:
  – one vtable per class with virtual function(s)
  – one pointer per instance
• Time:
  – one extra dereference if type not known at
    compile time
  – no penalty if type known at compile time
    (ok to inline a virtual function)

                   Engr. Anwar, Foundation University
                                                        43
                          (FUIEMS), Islamabad
Pure virtual function

• Pure virtual function
   – Function intentionally undefined
   – Same penalty as regular virtual function
• Abstract class
               class Shape {
                 virtual void Draw() = 0;
               };

   – Contains at least one pure virtual function
   – Cannot instantiate; must derive from base class and override pure
     virtual function
   – Provides an interface
     (separates interface from implementation)
                        Engr. Anwar, Foundation University
                                                                         44
                               (FUIEMS), Islamabad
class A {
public:
                      Virtual Functions
   A () {cout<<" A";}
                                        • Used to support polymorphism
   virtual ~A () {cout<<" ~A";}           with pointers and references
};                                      • Declared virtual in a base class
class B : public A {                    • Can be overridden in derived class
public:                                        – Overriding only happens when
   B () :A() {cout<<" B";}                       signatures are the same
   virtual ~B() {cout<<" ~B";}                 – Otherwise it just overloads the
};                                               function or operator name
int main (int, char *[]) {              • Ensures derived class function
   // prints "A B"                        definition is resolved dynamically
   A *ap = new B;                              – E.g., that destructors farther down the
                                                 hierarchy get called
     // prints "~B ~A" : would only
     // print "~A" if non-virtual
     delete ap;

     return 0;
};
                             Engr. Anwar, Foundation University
                                                                                   45
                                    (FUIEMS), Islamabad
class A {
public:              Virtual Functions
   void x() {cout<<"A:x";};
                                  •
   virtual void y() {cout<<"A:y";};        Only matter with pointer or reference
};                                           – Calls on object itself resolved statically
                                             – E.g., b.y();
class B : public A {              •        Look first at pointer/reference type
public:                                      – If non-virtual there, resolve statically
   void x() {cout<<"B:x";};                       • E.g., ap->x();
   virtual void y() {cout<<"B:y";};
                                             – If virtual there, resolve dynamically
};
                                                  • E.g., ap->y();
int main () {                         •    Note that virtual keyword need not be
   B b;                                    repeated in derived classes
   A *ap = &b; B *bp = &b;                   – But it’s good style to do so
   b.x (); // prints "B:x"            •    Caller can force static resolution of a
   b.y (); // prints "B:y"                 virtual function via scope operator
   bp->x (); // prints "B:x"                 – E.g., ap->A::y(); prints “A::y”
   bp->y (); // prints "B:y"
   ap.x (); // prints "A:x"
   ap.y (); // prints "B:y"
   return 0;
};
                           Engr. Anwar, Foundation University
                                                                                          46
                                  (FUIEMS), Islamabad
class A {
public:         Pure Virtual Functions
   virtual void x() = 0;
   virtual void y() = 0;
};                                • A is an Abstract Base Class
                                         – Similar to an interface in Java
class B : public A {
public:
                                         – Declares pure virtual functions (=0)
   virtual void x();              • Derived classes override pure virtual
};                                  methods
                                         – B overrides x(), C overrides y()
class C : public B {
public:                           • Can’t instantiate class with declared
   virtual void y();                or inherited pure virtual functions
};
                                         – A and B are abstract, can create a C
int main () {                     • Can still have a pointer to an
   A * ap = new C;                  abstract class type
   ap->x ();                             – Useful for polymorphism
   ap->y ();
   delete ap;
   return 0;
};
                           Engr. Anwar, Foundation University
                                                                                  47
                                  (FUIEMS), Islamabad
Early binding
• The term early binding means resolving a function
  call at compile-time.

• Examples of early binding include normal function
  calls and overloaded function calls.
•
• Early binding is used when all of the information
  needed to call a function is known at compile-time.



                   Engr. Anwar, Foundation University
                                                        48
                          (FUIEMS), Islamabad
Late binding
• The term late binding means resolving a function call
  at run-time.
• Late binding is used when some of the information
  needed to call a function is not known until run-time.
• Virtual function calls are an example of late binding.
• The decision on which derived class function to call is
  made at run time




                    Engr. Anwar, Foundation University
                                                         49
                           (FUIEMS), Islamabad
Summary: Tips on Polymorphism
• Push common code and variables up into base classes
• Use public inheritance for polymorphism
• Polymorphism depends on dynamic typing
   – Use a base-class pointer or reference if you want
     polymorphism
   – Use virtual member functions for dynamic overriding
• Use private inheritance only for encapsulation
• Use abstract base classes to declare interfaces
• Even though you don’t have to, label each virtual
  method (and pure virtual method) in derived classes

                       Engr. Anwar, Foundation University
                                                            50
                              (FUIEMS), Islamabad