#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }
};
int main(void)
{
typedef void(*Fun)(void);
Fun pFun = NULL;
Base b;
pFun = (Fun)(*((long *)(*((long *)(&b))) + 0));
pFun();//Base::f()
pFun = (Fun)(*((long *)(*((long *)(&b))) + 1));
pFun();//Base::g()
pFun = (Fun)(*((long *)(*((long *)(&b))) + 2));
pFun();//Base::h()
type_info *base_type = (type_info *)(*((long *)(*((long *)(&b))) - 1));
cout << "typeinfo is:" << base_type->name() << endl;
cout << "the result of typeid(Base).name():" << typeid(Base).name() << endl;
return 0;
}
the output is:
Base::f
Base::g
Base::h
typeinfo is:4Base
the result of typeid(Base).name():4Base
I use GCC 4.9.2 and my system is 64bit. so I use long
instead of int
.
type_info object is often stored at the first slot of the virtual
table.
This is wrong I think.
type_info object is often stored before the virtual table.
(long *)(*((long *)(&b)))
:this is the address of virtual table
(long *)(*((long *)(&b))) - 1
:this is the address of type_info object
so you see the result of the base_type->name()
is 4Base
. The result is the same as using typeid
.The 4
in 4Base
is the number of letters in your class name(Base
).more info here
ALSO:
when you complie the code with -fdump-class-hierarchy
,you could see the Vtable for Base
Vtable for Base
Base::_ZTV4Base: 5u entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI4Base)
16 (int (*)(...))Base::f
24 (int (*)(...))Base::g
32 (int (*)(...))Base::h
You could see _ZTI4Base
is before Base::f
use c++filt _ZTI4Base
would output typeinfo for Base