type_info

c++ type_info

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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;
}
1
2
3
4
5
Base::f                     
Base::g
Base::h
typeinfo is:4Base
the result of typeid(Base).name():4Base

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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)
{
Base* b = new Base;
const type_info & t = typeid(*b);
return 0;
}

部分汇编代码显示了vtable的布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Base::Base() [base object constructor]:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov edx, OFFSET FLAT:vtable for Base+16 # vptr指向了base::f()
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], rdx
nop
pop rbp
ret

vtable for Base:
.quad 0
.quad typeinfo for Base
.quad Base::f()
.quad Base::g()
.quad Base::h()
typeinfo for Base:
.quad vtable for __cxxabiv1::__class_type_info+16
.quad typeinfo name for Base
typeinfo name for Base:
.string "4Base" # 4代表类型名字的长度
...