#include <typeinfo>
#include <iostream>
class Person {
public:
virtual ~Person() {}
};
class Employee : public Person { };
int main()
{
Person person;
Employee employee;
Person* ptr = &employee;
Person& ref = employee;
std::cout << typeid(int).name() << std::endl;
std::cout << typeid(Employee).name() << std::endl;
{
const auto* pType = &typeid(*ptr);
}
std::cout << typeid(ptr).name() << std::endl;
std::cout << typeid(ref).name() << std::endl;
//type_info
return 0;
}
{
const auto* pType = &typeid(*ptr);
00C0DE09 mov eax,dword ptr [ptr]
00C0DE0C push eax
00C0DE0D call ___RTtypeid (0BF54F9h)
00C0DE12 add esp,4
00C0DE15 mov dword ptr [ebp-48h],eax
}
``
跳进去看实现:
```cpp
extern "C" void * __CLRCALL_OR_CDECL __RTtypeid (
void * inptr) // Pointer to polymorphic object
noexcept(false)
{
if (!inptr) {
throw std::bad_typeid::__construct_from_string_literal("Attempted a typeid of nullptr pointer!"); // WP 5.2.7
}
__try {
const auto pCompleteLocator = GetCompleteObjectLocatorFromObject(inptr);
#if _RTTI_RELATIVE_TYPEINFO
const auto _ImageBase = GetImageBaseFromCompleteObjectLocator(pCompleteLocator);
#endif
if (((const void *)COL_PTD(*pCompleteLocator)))
{
return (void *) COL_PTD(*pCompleteLocator);
}
else {
throw std::__non_rtti_object::__construct_from_string_literal("Bad read pointer - no RTTI data!");
}
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH)
{
throw std::__non_rtti_object::__construct_from_string_literal("Access violation - no RTTI data!");
}
}
这个很关键:
//
// _RTTICompleteObjectLocator
//
typedef const struct _s_RTTICompleteObjectLocator {
unsigned long signature;
unsigned long offset;
unsigned long cdOffset;
#if _RTTI_RELATIVE_TYPEINFO
int pTypeDescriptor; // Image relative offset of TypeDescriptor
int pClassDescriptor; // Image relative offset of _RTTIClassHierarchyDescriptor
int pSelf; // Image relative offset of this object
#else
TypeDescriptor* pTypeDescriptor;
_RTTIClassHierarchyDescriptor* pClassDescriptor;
#if VERSP_WIN64 // TRANSITION, VSO#515783
const _s_RTTICompleteObjectLocator* pSelf;
#endif // VERSP_WIN64
#endif
} _RTTICompleteObjectLocator;
#define COL_PTD(col) ((col).pTypeDescriptor)
``
显然返回的不是type_info 结构体
```cpp
#pragma warning(push)
#pragma warning(disable: 4577) // 'noexcept' used with no exception handling mode specified
class type_info
{
public:
type_info(const type_info&) = delete;
type_info& operator=(const type_info&) = delete;
size_t hash_code() const noexcept
{
return __std_type_info_hash(&_Data);
}
bool operator==(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) == 0;
}
bool operator!=(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) != 0;
}
bool before(const type_info& _Other) const noexcept
{
return __std_type_info_compare(&_Data, &_Other._Data) < 0;
}
const char* name() const noexcept
{
#ifdef _M_CEE_PURE
return __std_type_info_name(&_Data, static_cast<__type_info_node*>(__type_info_root_node.ToPointer()));
#else
return __std_type_info_name(&_Data, &__type_info_root_node);
#endif
}
const char* raw_name() const noexcept
{
return _Data._DecoratedName;
}
virtual ~type_info() noexcept;
private:
mutable __std_type_info_data _Data;
};
typedef struct TypeDescriptor
{
#if defined(_WIN64) || defined(_RTTI) || defined(BUILDING_C1XX_FORCEINCLUDE)
const void * pVFTable; // Field overloaded by RTTI
#else
unsigned long hash; // Hash value computed from type's decorated name
#endif
void * spare; // reserved, possible for RTTI
char name[]; // The decorated name of the type; 0 terminated.
} TypeDescriptor;
但是从二进制级别比较的话,其实TypeDescriptor 中的pVFTable 和
virtual ~type_info() noexcept; 重叠,由此,二进制级别是一样的.
算是vs 的常规操作吧