i know that in polymorphism when we not use virtual function then the compiler is execuite member function according to pointer type and when we use virtual function then compiler execute member function according to the type of object
My question is that WHY it is happnes what is the functionality of virtual function that force the compiler to execute member function according to type of object. what is the logic in virtual function plz answer my question

The mechanism for calling virtual function is, technically-speaking, unspecified or implementation-defined, meaning that there is not actual guarantee about how it is actually done. However, it is almost always accomplished the same way, via a virtual table. So, for each class that defines or inherits virtual functions, the compiler will generate a table (array) of function pointers, each pointing to the appropriate function.

The table is laid out such that each specific function has its specific place (index) in that table. And the placement of the functions is essentially hierarchical for all the inheriting classes. So, let's say you have classes A, B, and C, where C derives from B, which derives from A. Say that A has a virtual destructor (as all base classes should) and a virtual function called "foo". Then, B has a virtual function called "bar" and C has one called "foobar". Then, the virtual table for class A will have (destructor, "foo") in it, then the table for class B will have (destructor, "foo", "bar") in it (in that order), and finally, C will have (destructor, "foo", "bar", "foobar"). Because of this hierarchy, the virtual table of C "looks like" a virtual table for class A, if you only look at the first two entries. That's how that works.

Finally, whenever you create an object, there is a pointer within that object (which you cannot see, because the compiler generates it for you), and that pointer points to the virtual table of the most-derived class it belongs to (e.g., class C in above example). The constructor takes care of initializing that pointer for you, and we call that pointer the "virtual table pointer" (or for short, vtable pointer or vt-ptr).

When a virtual function is called, what actually happens is that the address stored in the vtable pointer is taken, an offset is added to it to move to the desired function, and whatever function pointer is at that location in the virtual table points to the function that needs to be called (i.e., the most-derived implementation of that virtual function). Because the vtable pointer depends on the type of the object (which is determined at creation of the object), the function call also depends on the type of the object, and that is how this whole mechanism is realized.

For those interested in how all of this works in detail, here is a simple snippet of code that I wrote which shows the equivalence between a simple piece of polymorphic C++ code, and it's equivalent if C++ were more like C (no support for virtual functions or member functions):

#include <iostream>

// #define USE_CPP_OOP_FEATURES

#ifdef USE_CPP_OOP_FEATURES

class Base {
  public:
    int some_value;

    Base(int aSomeValue) : some_value(aSomeValue) { };

    virtual ~Base() { };

    virtual void print() const {
      std::cout << "Some value is " << some_value << std::endl;
    };

};

class Derived : public Base {
  public:
    int some_other_value;

    Derived(int aSomeValue, int aSomeOtherValue) : 
            Base(aSomeValue), some_other_value(aSomeOtherValue) { };

    virtual ~Derived() { };

    virtual void print() const {
      std::cout << "Some value is " << some_value << " and some other value is " << some_other_value << std::endl;
    };

    virtual int multiply() const {
      return some_value * some_other_value;
    };

};

int main() {
  Derived d(42, 69);
  Base* pb = &d;
  pb->print();

  Base b(d.multiply());
  b.print();

  return 0;
};

#else

// Define some basic function pointer type:
typedef void (*void_func_t)(void);

struct Base {
  void_func_t* vt_ptr;
  int some_value;
};

// --- Internal 'hidden' things associated to the 'Base' class:

void Base_destroy_virtual(Base* p_this) { 
  // since object is about to die, invalidate the vt-pointer
  p_this->vt_ptr = NULL;
};

void Base_print_virtual(const Base* p_this) {
  std::cout << "Some value is " << p_this->some_value << std::endl;
};

// Create a virtual table for the 'Base' class:
void_func_t Base_vtable[] = {
  reinterpret_cast<void_func_t>(&Base_destroy_virtual),  // pointer to destructor
  reinterpret_cast<void_func_t>(&Base_print_virtual)     // pointer to print-function
};

// --- External 'published' things associated to the 'Base' class;

void Base_construct(Base* p_this, int aSomeValue) {
  // Set virtual table pointer to the start of 'Base' virtual table:
  p_this->vt_ptr = Base_vtable;
  // Initialize data members:
  p_this->some_value = aSomeValue;
};

void Base_destroy(Base* p_this) {
  // Obtain a pointer to the actual destructor (index 0 in virtual table):
  typedef void (*destroy_ptr_t)(Base*);
  destroy_ptr_t destroy = reinterpret_cast<destroy_ptr_t>(p_this->vt_ptr[0]);
  // Call the destructor:
  destroy(p_this);
};

void Base_print(const Base* p_this) {
  // Obtain a pointer to the actual print function (index 1 in virtual table):
  typedef void (*print_ptr_t)(const Base*);
  print_ptr_t print = reinterpret_cast<print_ptr_t>(p_this->vt_ptr[1]);
  // Call the print function:
  print(p_this);
};


struct Derived : Base {
  int some_other_value;
};

// --- Internal 'hidden' things associated to the 'Derived' class:

void Derived_destroy_virtual(Base* p_this) { // receive as base-class pointer, then cast to derived:
  Derived* p_this_derived = static_cast<Derived*>(p_this);
  // since object is about to die, reset the vt-pointer to the 'Base' class:
  p_this_derived->vt_ptr = Base_vtable;
  // call the base-class destructor:
  Base_destroy_virtual(p_this);
};

void Derived_print_virtual(const Base* p_this) { // receive as base-class pointer, then cast to derived:
  const Derived* p_this_derived = static_cast<const Derived*>(p_this);
  std::cout << "Some value is " << p_this_derived->some_value 
            << " and some other value is " << p_this_derived->some_other_value << std::endl;
};

int Derived_multiply_virtual(const Derived* p_this) {
  return p_this->some_value * p_this->some_other_value;
};

// Create a virtual table for the 'Derived' class:
void_func_t Derived_vtable[] = {
  reinterpret_cast<void_func_t>(&Derived_destroy_virtual),  // pointer to destructor
  reinterpret_cast<void_func_t>(&Derived_print_virtual),    // pointer to print-function
  reinterpret_cast<void_func_t>(&Derived_multiply_virtual)  // pointer to multiply-function
};

// --- External 'published' things associated to the 'Derived' class;

void Derived_construct(Derived* p_this, int aSomeValue, int aSomeOtherValue) {
  // First, call the base-class constructor:
  Base_construct(p_this, aSomeValue);
  // Set virtual table pointer to the start of 'Derived' virtual table:
  p_this->vt_ptr = Derived_vtable;
  // Initialize the 'other' data member:
  p_this->some_other_value = aSomeOtherValue;
};

void Derived_destroy(Derived* p_this) {
  // Obtain a pointer to the actual destructor (index 0 in virtual table):
  typedef void (*destroy_ptr_t)(Base*);
  destroy_ptr_t destroy = reinterpret_cast<destroy_ptr_t>(p_this->vt_ptr[0]);
  // Call the destructor:
  destroy(p_this);
};

void Derived_print(const Derived* p_this) {
  // Obtain a pointer to the actual print function (index 1 in virtual table):
  typedef void (*print_ptr_t)(const Base*);
  print_ptr_t print = reinterpret_cast<print_ptr_t>(p_this->vt_ptr[1]);
  // Call the print function:
  print(p_this);
};

int Derived_multiply(const Derived* p_this) {
  // Obtain a pointer to the actual multiply function (index 2 in virtual table):
  typedef int (*multiply_ptr_t)(const Derived*);
  multiply_ptr_t multiply = reinterpret_cast<multiply_ptr_t>(p_this->vt_ptr[2]);
  // Call the multiply function:
  return multiply(p_this);
};


int main() {
  Derived d;
  Derived_construct(&d, 42, 69);
  Base* pb = &d;
  Base_print(pb);

  Base b;
  Base_construct(&b, Derived_multiply(&d));
  Base_print(&b);

  Base_destroy(&b);
  Derived_destroy(&d);
  return 0;
};

#endif

If you compile with or without the USE_CPP_OOP_FEATURES macro defined, you can clearly see that the two versions are equivalent. And you can also see from the above, why it is so convenient to have the compiler generate all this code instead of having to write it up manually (which people sometimes do, e.g., to write object-oriented code in C). There are quite a few subtle issues in that code, so, it's worth taking a close look at.

And also, if you start talking about multiple and virtual inheritance, things could get a lot more complicated.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.