ポインタが他のクラスにキャスト可能か調べる
なんか dynamic_cast<> のソースを見つけたので、それを改造して作ってみた。
#include <typeinfo.h> typedef void (*v_table_ptr)(); typedef struct _cpp_object { v_table_ptr* vtable; } cpp_object; typedef struct _rtti_base_descriptor { type_info* type_descriptor; int num_base_classes; int base_class_offset; unsigned int flags; int unknown1; int unknown2; } rtti_base_descriptor; typedef struct _rtti_base_array { const rtti_base_descriptor* bases[3]; } rtti_base_array; typedef struct _rtti_object_hierachy { int unknown1; int unknown2; int array_len; const rtti_base_array* base_classes; } rtti_object_hierachy; typedef struct _rtti_object_locator { int unknown1; int base_class_offset; unsigned int flags; type_info* type_descriptor; const rtti_object_hierachy* type_hierachy; } rtti_object_locator; bool IsCast(void* ptr, const type_info& targetType) { cpp_object* cppobj = (cpp_object*) ptr; type_info* dst = (type_info*)&targetType; const rtti_object_locator* obj_locator; obj_locator = (rtti_object_locator*)cppobj->vtable[-1]; if (obj_locator) { int count = 0; const rtti_object_hierachy* obj_bases = obj_locator->type_hierachy; const rtti_base_descriptor* const * base_desc = obj_bases->base_classes->bases; bool found = false; while (count < obj_bases->array_len) { const type_info* typ = (*base_desc)->type_descriptor; if (typ == dst) { found = true; break; } base_desc++; count++; } return found; } return false; }
struct A { virtual ~A() { } }; struct B : public A { }; int main(int argc, char* argv[]) { B b; A* pa = &b; if (IsCast(pa, typeid(B))) { B* pb = static_cast<B*>(pb); ... } return 0; }
何というコンパイラ依存コードw
あ、もちろん仮想テーブルとか RTTI とか無いポインタを渡すとアウトですよ。
そういえば、これだとオフセット値が分かんないから、キャスト可能って返されてキャストするとおかしなことになってしまうっぽい。
ということでちゃんと dynamic_cast<> のコードの通りやって NULL が返されるかどうかを見た方がよさげ。