Understanding virtuality
This article is still under construction. I need to add the text ;)
The simple case

class Foo
{
public:
  Foo() : a(1), b(2), c(3) {}
public:
  void f() { std::cout << "Foo::f()" << std::endl; }
  void g() { std::cout << "Foo::g()" << std::endl; }
public:
  int a;
  int b;
  int c;
};
int main( int, char** )
{
  Foo foo;
  
  std::cout << "sizeof(Foo)= " << sizeof(Foo) << std::endl;
  std::cout << std::endl;
  std::cout << "(int*)&foo+0=    " << (int*)&foo+0    << std::endl;
  std::cout << "&foo.a=          " << &foo.a          << std::endl;
  std::cout << "foo.a=           " << foo.a           << std::endl;
  std::cout << "*((int*)&foo+0)= " << *((int*)&foo+0) << std::endl;
  std::cout << std::endl;
  std::cout << "&foo.b=          " << &foo.b          << std::endl;
  std::cout << "(int*)&foo+1=    " << (int*)&foo+1    << std::endl;
  std::cout << "foo.b=           " << foo.b           << std::endl;
  std::cout << "*((int*)&foo+1)= " << *((int*)&foo+1) << std::endl;
  std::cout << std::endl;
  std::cout << "&foo.c=          " << &foo.c          << std::endl;
  std::cout << "(int*)&foo+2=    " << (int*)&foo+2    << std::endl;
  std::cout << "foo.c=           " << foo.c           << std::endl;
  std::cout << "*((int*)&foo+2)= " << *((int*)&foo+2) << std::endl;
  
  return EXIT_SUCCESS;
}
Output:
sizeof(Foo)= 12 (int*)&foo+0= 0xbffff7c4 &foo.a= 0xbffff7c4 foo.a= 1 *((int*)&foo+0)= 1 &foo.b= 0xbffff7c8 (int*)&foo+1= 0xbffff7c8 foo.b= 2 *((int*)&foo+1)= 2 &foo.c= 0xbffff7cc (int*)&foo+2= 0xbffff7cc foo.c= 3 *((int*)&foo+2)= 3
Introducing virtuality

class Foo
{
public:
  Foo() : a(1), b(2), c(3) {}
public:
  virtual void f() { std::cout << "Foo::f()" << std::endl; }
  virtual void g() { std::cout << "Foo::g()" << std::endl; }
public:
  int a;
  int b;
  int c;
};
int main( int, char** )
{
  Foo foo;
  
  std::cout << "sizeof(Foo)= " << sizeof(Foo) << std::endl;
  std::cout << std::endl;
  std::cout << "(int (***)(...))&foo+0=    " << (int (***)(...))&foo+0    << std::endl;
  std::cout << "&foo._vptr=                " << &foo._vptr                << std::endl;
  std::cout << "foo._vptr=                 " << foo._vptr                 << std::endl;
  std::cout << "*((int (***)(...))&foo+0)= " << *((int (***)(...))&foo+0) << std::endl;
  std::cout << std::endl;
  std::cout << "(int*)&foo+1=    " << (int*)&foo+1    << std::endl;
  std::cout << "&foo.a=          " << &foo.a          << std::endl;
  std::cout << "foo.a=           " << foo.a           << std::endl;
  std::cout << "*((int*)&foo+1)= " << *((int*)&foo+1) << std::endl;
  std::cout << std::endl;
  std::cout << "&foo.b=          " << &foo.b          << std::endl;
  std::cout << "(int*)&foo+2=    " << (int*)&foo+2    << std::endl;
  std::cout << "foo.b=           " << foo.b           << std::endl;
  std::cout << "*((int*)&foo+2)= " << *((int*)&foo+2) << std::endl;
  std::cout << std::endl;
  std::cout << "&foo.c=          " << &foo.c          << std::endl;
  std::cout << "(int*)&foo+3=    " << (int*)&foo+3    << std::endl;
  std::cout << "foo.c=           " << foo.c           << std::endl;
  std::cout << "*((int*)&foo+3)= " << *((int*)&foo+3) << std::endl;
  
  return EXIT_SUCCESS;
}
Output:
sizeof(Foo)= 16 (int (***)(...))&foo+0= 0xbffff7c0 &foo._vptr= 0xbffff7c0 foo._vptr= 0x2040 *((int (***)(...))&foo+0)= 0x2040 (int*)&foo+1= 0xbffff7c4 &foo.a= 0xbffff7c4 foo.a= 1 *((int*)&foo+1)= 1 &foo.b= 0xbffff7c8 (int*)&foo+2= 0xbffff7c8 foo.b= 2 *((int*)&foo+2)= 2 &foo.c= 0xbffff7cc (int*)&foo+3= 0xbffff7cc foo.c= 3 *((int*)&foo+3)= 3
class Foo
{
public:
  Foo() : a(1), b(2), c(3) {}
public:
  virtual void f() { std::cout << "Foo::f()" << std::endl; }
  virtual void g() { std::cout << "Foo::g()" << std::endl; }
public:
  int a;
  int b;
  int c;
};
union MemberPtrMixin
{
  void (Foo::*pfn)(); // The real type of our Foo methods
  int (*pvt)(...);    // The global type of a vtable entry
};
int main( int, char** )
{
  Foo foo;
  
  std::cout << "foo.f()= "; (foo.*(&Foo::f))();
  std::cout << "foo.g()= "; (foo.*(&Foo::g))();
  
  std::cout << std::endl;
  
  std::cout << "(foo.*(&Foo::f))()= "; (foo.*(&Foo::f))();
  std::cout << "(foo.*(&Foo::g))()= "; (foo.*(&Foo::g))();
  
  std::cout << std::endl;
  
  MemberPtrMixin pmb_f;
  MemberPtrMixin pmb_g;
  pmb_f.pvt = foo._vptr[0];
  pmb_g.pvt = foo._vptr[1];
  std::cout << "(foo.*pmb_f.pfn)()= "; (foo.*pmb_f.pfn)();
  std::cout << "(foo.*pmb_g.pfn)()= "; (foo.*pmb_g.pfn)();
  
  return EXIT_SUCCESS;
}
Output:
foo.f()= Foo::f() foo.g()= Foo::g() (foo.*(&Foo::f))()= Foo::f() (foo.*(&Foo::g))()= Foo::g() (foo.*pmb_f.pfn)()= Foo::f() (foo.*pmb_g.pfn)()= Foo::g()
Final example

class Foo
{
public:
  Foo() : a(1), b(2), c(3) {}
public:
  virtual void f() { std::cout << "Foo::f()" << std::endl; }
  virtual void g() { std::cout << "Foo::g()" << std::endl; }
public:
  int a;
  int b;
  int c;
};
class Bar : public Foo
{
public:
  virtual void g() { std::cout << "Bar::g()" << std::endl; }
};
union MemberPtrMixin
{
  void (Bar::*pfn)(); // The real type of our Bar methods
  int (*pvt)(...);    // The global type of a vtable entry
};
int main( int, char** )
{
  Bar bar;
  
  std::cout << "bar.f()= "; (bar.*(&Bar::f))();
  std::cout << "bar.g()= "; (bar.*(&Bar::g))();
  
  std::cout << std::endl;
  
  std::cout << "(bar.*(&Bar::f))()= "; (bar.*(&Bar::f))();
  std::cout << "(bar.*(&Bar::g))()= "; (bar.*(&Bar::g))();
  
  std::cout << std::endl;
  
  MemberPtrMixin pmb_f;
  MemberPtrMixin pmb_g;
  pmb_f.pvt = bar._vptr[0];
  pmb_g.pvt = bar._vptr[1];
  std::cout << "(bar.*pmb_f.pfn)()= "; (bar.*pmb_f.pfn)();
  std::cout << "(bar.*pmb_g.pfn)()= "; (bar.*pmb_g.pfn)();
  
  return EXIT_SUCCESS;
}
Output:
bar.f()= Foo::f() bar.g()= Bar::g() (bar.*(&Bar::f))()= Foo::f() (bar.*(&Bar::g))()= Bar::g() (bar.*pmb_f.pfn)()= Foo::f() (bar.*pmb_g.pfn)()= Bar::g()
 
       
       
      