Virtual Functions in C++

Discussion in 'C++' started by Shishir191, Jul 27, 2007.

  1. Shishir191

    Shishir191 New Member

    Joined:
    Jul 24, 2007
    Messages:
    27
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Software Engineer
    Location:
    Delhi
    Sometimes its very difficult to understand which function would be call. So, this example explain you about how member functions are called while using virtual and without virtual.

    1) Example of Virtual Function



    In the case of virtual function when we call the member functions.The compiler knows which member function has to call it depends upon the type of object.

    Like according to the example there is one virtual function "Show" in both the base and derived class.

    And the output is :

    -- I am in Test1 Class
    -- I am in Test Class

    First Derived class Show function called because first we pass the Derived class Object to the base class pointer. And i said earlier in case of virtual function complier knows which member function has to call depends upon the type of object.

    Code:
    #include<iostream.h>
    #include<conio.h>
    
    class Test
    {
    	public :
    
    		virtual Show()
    		{
    			cout<<"I am in Test Class"<<endl;
    		}
    };
    
    class Test1 : public Test
    {
          public:
    	       virtual Show()
    	       {
    			cout<<"I am in Test1 Class"<<endl;
    	       }
    
    };
    
    void main()
    {
    	Test *Obj;
    
    	Test Obj1;   // Base Class Object
    
    	Test1 Obj2;  //Derived Class Object
    
    	Obj = &Obj2;
    
    	Obj->Show();  //In this case derived class show function called.
    
    	Obj = &Obj1;
    
    	Obj->Show(); //In this case Base class show function called.
    }

    2) Example of Non Virtual Function



    In the case of Non virtual function when we call the member functions.The compiler knows which member function has to call it depends upon the type of pointer.

    Like according to the example there is one Non virtual function "Show" in both the base and derived class.

    And the output is :

    -- I am in Test Class
    -- I am in Test Class

    In this case base class Show function called twice even though when have passed the Derived class Object to the base class pointer. Then also base class "Show" function has called twice.

    This is happened because in this case compiler knows which member function has to call it depends upon the type of pointer not the type of Object.

    Because i have defined base class pointer thats why base class "Show" function has called twice. If you defined Derived Class pointer then derived class member function will call twice.

    Code:
    #include<iostream.h>
    #include<conio.h>
    
    class Test
    {
    	public :
    
    		void Show()  //Without virtual 
    		{
    			cout<<"I am in Test Class"<<endl;
    		}
    };
    
    class Test1 : public Test
    {
          public:
    	       virtual Show()
    	       {
    			cout<<"I am in Test1 Class"<<endl;
    	       }
    
    };
    
    void main()
    {
    	Test *Obj;
    
    	Test Obj1;   // Base Class Object
    
    	Test1 Obj2;  //Derived Class Object
    
    	Obj = &Obj2;
    
    	Obj->Show();  //In this case derived class show function called.
    
    	Obj = &Obj1;
    
    	Obj->Show(); //In this case Base class show function called.
    }
     
  2. rivthebest

    rivthebest New Member

    Joined:
    Nov 28, 2007
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    I believe that the Virtual Function Concept can be implemented in the following way::

    In your example you have used virtual keywords in the Derived class also. It does not create any problem while compiling and runnnig. But we do not require the virtual keyword in the
    Derived class's function definition.

    Over here I would like to show the different scenarios of Inheritance as well.

    First Case::

    I have inherited the Base Class by Public access specifier. The function(method) is defined under the public class access specifer in the class for both Base and Derived1 and Derived2.

    Code:
    #include <iostream>
    #include <conio.h>
    
    using namespace std;
    
    class Base
    {
          public:
                 virtual void show() 
                 { cout << "\nBase."; }
    };
    
    class Derived1 : public Base
    {
          private:
                 void show()
                 { cout << "\nDerived1."; }
    };
    
    class Derived2 : public Base
    {
          private:
                 void show()
                 { cout << "\nDerived2."; }
    };
    
    int main()
    {
        Base *ptr;
        Derived1 dv1;
        Derived2 dv2;
        
        ptr -> Base::show(); // this is a correct implementation for accessing the content of the
                                       // Base class
        
        // assigning the address of the object of the Derived1 class to the pointer of the Base
       //  class.
        ptr = &dv1;
        ptr -> show();
        
         // assigning the address of the object of the Derived2 class to the pointer of the Base
       //  class.
        ptr = &dv2;
        ptr -> show();
        
        getch();
        
        return 0;
    }
    
    The corresponding output of the above mentioned code will be::

    Base.
    Derived1.
    Derived2.

    Base Class pointer has no problem while getting assigned in the Derived class object, as compiler is comfortable with this kind of assignment.

    I have also shown the result of the show() function written in the Base class. I have not created any object of the Base class. Only the unnamed object of the Base class help me to work with the function written in the Base class. The unnamed object can be declared as the following syntax

    <Class Name>::<method Name>(i.e. the Class Name then scope resolution operator [double colon] and the method name in that class)

    The compiler chooses the appropriate function at run time. Because the Base class pointer is containing the address of the Derived class object which is chosen at run time. This is called "Dynamic Binding".

    Now I will make some small changes in the main function so where I will not assign the address of the Dervied Class to the Base Class Pointer and directly execute the functions with the Derived Class objects.

    Here is the details::
    Code:
    int main()
    {
    
         Base *ptr;
         Derived1 dv1;
         Derived2 dv2;
         
         // executing the Base class show() function
         ptr -> Base::show();
    
         // executing the Derived1 class show() function
        dv1.show();
    
        // executing the Derived2 class show() function
        dv2.show();
    
       getch();
    
       return 0;
    }
    
    N.B. As I have used Bloodshed Dev-C++ as the IDE so I had to use getch() in the main function to trap the output. It won't require who are using Linux or Unix systems and please remove <conio.h> header file instruction if you are using Unix or Linux systems.

    I will get the same output as above.

    Second Case::

    Now I will make some changes in the class definitions of the Derived Classes:

    The method show() is been written in the private class specifier section of the Derived class and I have declared the object of the Base Class pointer and I have assigned each of the Derived class object one at time to execute the show() method.

    The result will be just as above. Here is the definition of the classes::
    Code:
    #include <iostream>
    #include <conio.h>
    
    using namespace std;
    
    class Base
    {
          public:
                 virtual void show() // declaring virtual function
                 { cout << "\nBase."; }
    };
    
    class Derived1 : public Base
    {
          private:
                 void show()
                 { cout << "\nDerived1."; }
    };
    
    class Derived2 : public Base
    {
          private:
                 void show()
                 { cout << "\nDerived2."; }
    };
    
    
    Now if you do not use Pointers to the Base class object and directly use the Derived class object to get the function show() of the Derived class the compiler will start complaining, because the show() function is defined within the class scope of private.

    Third Case:

    Same thing will happen if the Class Access specifier is declared as protected for the member function show() in the Derived classes Derived1 and Derived2 and the base class is inherited as public access specifier and in the main function if through the Base class pointer derived class object is accessed.

    Fourth Case:
    Other than public class access specifier for inheriting the Base class to the Derived class if protected or private access specifier is used for inheritance then nothing can be done. Because Base class objects will be inaccessible to the Derived class.

    The other way round of the problem is if in the Base class the methods are written in the private class access specifier then similar kind of thing will happen.

    I will be anxiously waiting for your reply.

    Thank you

    Riv.
     
  3. asadullah.ansari

    asadullah.ansari TechCake

    Joined:
    Jan 9, 2008
    Messages:
    356
    Likes Received:
    14
    Trophy Points:
    0
    Occupation:
    Developer
    Location:
    NOIDA
    Just See the Code , Very simple you can understand Very well. No confusion very straightforward!!!

    Code:
    class Base1 {
      virtual void f() { cout << “Base1::f” << endl; }
      virtual void g() { cout << “Base1::g” << endl; }
    };
    
    class Base2 {
      virtual void f() { cout << “Base2::f” << endl; }
      virtual void g() { cout << “Base2::g” << endl; }
    };
    
    class Base3 {
      virtual void f() { cout << “Base3::f” << endl; }
      virtual void g() { cout << “Base3::g” << endl; }
    };
    
    class Drive : public Base1, public Base2, public Base3 {
    public:
     virtual void fd() { cout << “Drive::fd” << endl; }
     virtual void gd() { cout << “Drive::gd” << endl; }
    };
    
    typedef void(*Fun)(void);
    
    int main() {
      Drive objDrive;
    
      Fun pFun = NULL;
    
      // calling 1st virtual function of Base1
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+0);
      pFun();
    
      // calling 2nd virtual function of Base1
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+1);
      pFun();
    
      // calling 1st virtual function of Base2
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+1)+0);
      pFun();
    
      // calling 2nd virtual function of Base2
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+1)+1);
      pFun();
    
      // calling 1st virtual function of Base3
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+2)+0);
      pFun();
    
      // calling 2nd virtual function of Base3
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+2)+1);
      pFun();
    
      // calling 1st virtual function of Drive
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+2);
      pFun();
    
      // calling 2nd virtual function of Drive
      pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+3);
      pFun();
    
      return 0;
    }
    
    The output of this program is
    Base1::f
    Base1::g
    Base2::f
    Base2::g
    Base3::f
    Base3::g
    Drive::fd
    Drive::gd

    VPTR OF Base1 &f()
    &g()
    &fd()
    &gd()

    VPTR Od Base2 &f()
    &g()
    VPTR OF Base3 &f()
    &g()


    i.e. Only One Vtable is made for base, Derived….


    Picture of VPTRs are as—–>>>>>>

    VPTR OF Base1
    &f()
    &g()
    &fd()
    &gd()

    VPTR Od Base2
    &f()
    &g()
    VPTR OF Base3
    &f()
    &g()
     
    Last edited by a moderator: Jan 11, 2008
  4. talk2mohdsaif

    talk2mohdsaif New Member

    Joined:
    Mar 8, 2009
    Messages:
    21
    Likes Received:
    0
    Trophy Points:
    0
    Location:
    Hamirpur(hp)
    can u tell me ..
    what is the importance of virtual table ???
    and why vtable made???
     
  5. vanamadi

    vanamadi New Member

    Joined:
    Dec 29, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Hi all,
    for the below program
    sizeof base class=4bytes;
    sizeof derived class=4bytes;


    which function address getting stored in the derived VPTR table and why?
    or
    second time calling of pFun() in the below code will call which function and why?


    Code:
    class Base
     
    { 
    public:
    virtual  void show() 
     { 
       cout << "Base::show()" << endl; 
     }    
    
     void display() 
     { 
      cout << "Base::display()" << endl;
     }
    };
    class Derive : public Base
    {
    public: 
     void show() 
    { 
     cout << "derived::show()" << endl; 
    }
     void display() 
    { 
     cout << "derived::display()" << endl; 
    }
    
    };
     
    main(){
     
    Derive D;
    Base B;
    cout<<"sizeof base class="<<sizeof(B)<<endl;
    pFun = (Fun)*((int*)*(int*)((int*)&B+0)+0);
    pFun();
    cout<<"sizeof Derived class="<<sizeof(D)<<endl;
    pFun = (Fun)*((int*)*(int*)((int*)&D+0)+0);
    pFun();
    cout<<"vartual derived addres="<<pFun<<endl;
    }
    with regards,
    venkat
     
    Last edited by a moderator: Dec 29, 2009
  6. bodhisattwa

    bodhisattwa New Member

    Joined:
    Jan 29, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    student
    Location:
    kolkata
    nice post to understand virtual function..thanks
     
  7. davidk

    davidk New Member

    Joined:
    Mar 25, 2010
    Messages:
    16
    Likes Received:
    1
    Trophy Points:
    0
    Home Page:
    http://www.firmdev.com/firm_framework
    To understand how to use virtual functions you have to understand why to use them at all.

    Consider this example:
    Code:
    #include <stdio.h>
    class Animal
    {public:
    	virtual void say() = 0;
    };
    class Cow : public Animal
    {
    public:
    	/*override*/ void say()
    	{
    		puts("Mooo");
    	}
    };
    class Dog : public Animal
    {public:
    	/*override*/ void say()
    	{
    		puts("Arrrrgh");
    	}
    };
    
    Why we are using virtual functions here? What do you think?
    The answer is: we need the ability to call say() function from the Animal class which knows really nothing about those who derive from it.
    The example of how to use these classes is:
    Code:
    int main()
    {
    	Animal **animals = new Animal *[2]; //create an array of animals
    	animals[0] = new Cow(); //add cow
    	animals[1] = new Dog(); //add dog
    	for(int i = 0; i < 2; i++)
    		animals[i]->say(); //call say() function of each animal
    	//...
    }
    
    We may use thousands of animals here and still we call say() function from the array of animals and get different results depending on what animal exactly it is.
    Ask me, if something is unclear in the examples above.
     
    shabbir likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice