Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Virtual Functions in C++ (http://www.go4expert.com/articles/virtual-functions-cpp-t5495/)

Shishir191 27Jul2007 19:04

Virtual Functions in C++
 
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: Cpp

#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: Cpp

#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.
}


rivthebest 30Nov2007 19:37

Re: Virtual Functions in C++
 
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.

asadullah.ansari 11Jan2008 10:35

Re: Virtual Functions in C++
 
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()

talk2mohdsaif 15Nov2009 17:40

Re: Virtual Functions in C++
 
can u tell me ..
what is the importance of virtual table ???
and why vtable made???

vanamadi 29Dec2009 08:59

Re: Virtual Functions in C++
 
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

bodhisattwa 30Jan2010 00:50

Re: Virtual Functions in C++
 
nice post to understand virtual function..thanks

davidk 26Mar2010 12:56

Re: Virtual Functions in C++
 
To understand how to use virtual functions you have to understand why to use them at all.

Consider this example:
Code: cpp

#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: cpp

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.


All times are GMT +5.5. The time now is 08:58.