I executed the following code.
#include <iostream>
class Base
{
public:
virtual void func()
{
std::cout<<"Base func called"<<std::endl;
}
};
class Derived: public Base
{
public:
virtual void func() override
{
std::cout<<"Derived func called"<<std::endl;
}
};
int main()
{
void (Base::*func_ptr)()=&Base::func; //Yes, the syntax is very beautiful.
Base* bptr=new Derived();
(bptr->*func_ptr)();
}
My expected output was Base func called. However, Instead, the output was
Derived func called
Which surprised me, because I think that func_ptr should be able to see only Base members(because I thought that func_ptr doesn't access the member function via _vptr, but the function address itself.
I would like to know, how the virtual dispatch takes place in this case(how the access to virtual table takes place), and where this behavior is defined in C++ standard(I couldn't find anything)?
Refer to [expr.call], specifically here
Whether you call the function through a pointer or by class member access is the same (ref); the actual function called for a virtual function ultimately depends on the actual type of the object it is being called on.
A few (non-normative) notes in the standard under [class.virtual] say much the same thing:
If you would like to know how the virtual function dispatch takes place, you will need to seek out a specific implementation, because the how is not standardized.
(I really enjoyed the article A basic glance at the virtual table, which shows one possible way you could implement it using C)