我从“ Inside C ++ Object Model ”中读到,type_info对象通常存储在虚拟表的第一个插槽中。但是,我迭代了虚拟表中的成员:
class Base {
public:
virtual void f() { cout << "Base::f" << endl; }
virtual void g() { cout << "Base::g" << endl; }
virtual void h() { cout << "Base::h" << endl; }
};
typedef void(*Fun)(void);
Base b;
(Fun)*((int*)*(int*)(&b)+0); // Base::f()
(Fun)*((int*)*(int*)(&b)+1); // Base::g()
(Fun)*((int*)*(int*)(&b)+2); // Base::h()
从最后三行看,我根本找不到type_info。
答案 0 :(得分:6)
没有交叉编译方式从对象的地址获取type_info
。你也不期望会有;获取type_info
的方法是使用特定的C ++关键字:typeid
。
答案 1 :(得分:0)
#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;
}
输出是:
Base::f
Base::g
Base::h
typeinfo is:4Base
the result of typeid(Base).name():4Base
我使用GCC 4.9.2,我的系统是64位。所以我使用long
代替int
。
type_info对象通常存储在虚拟的第一个插槽中 表
我认为这是错误的
type_info对象通常存储在虚拟表之前。
(long *)(*((long *)(&b)))
:这是虚拟表的地址
(long *)(*((long *)(&b))) - 1
:这是type_info对象的地址
所以你看到base_type->name()
的结果是4Base
。结果与使用typeid
相同。4
中的4Base
是您的班级名称中的字母数(Base
)。more info here
ALSO:
当您使用-fdump-class-hierarchy
编译代码时,您可以看到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
您可以在_ZTI4Base
之前看到Base::f
使用c++filt _ZTI4Base
会输出typeinfo for Base
答案 2 :(得分:-1)
只有为某些编译器启用RTTI(运行时类型信息)编译标志时,
type_info才可用。