dynamic_cast, RTTI, 整理

主要是参考下图,了解内存布局,然后写个实例程序就差不多明白了,但是需要熟悉指针转换。

1) 只有多态类才有RTTI信息,dynamic_cast正是运用RTTI进行转换,属于运行时类型检查。

2) dynamic_cast判断两个指针是否能转换时,用RTTI可以知道当前实际对象,然后遍历自己所有的父类,看是否有与目标类型一致的,如果有就可以进行转换。

3) dynamic_cast是安全的,可以通过检查返回值或异常捕捉来判断是否转成功。其中检查返回值用于指针转换,异常捕捉用于引用转换。

4) 补充一点,与static_cast不同,即使两个类没有直接继承关系,但是只要在一个类层次结构中,就有可能指向同一个对象,也就可以进行dynamic_cast。以下图为例,C继承自A,B。A, B指针就可以进行dynamic_cast,并可能成功。

C * pc = new C;
    A* pa = pc;
    B* pb = pc;

pb = dynamic_cast<B*>(pa); // 可以成功进行转换,因为二者指向的都是C对象。

下面的例子主要是关于RTTI的,打印出一个对象和她所有父类的运行时信息,这里的运行时信息主要是类的名字。

#include "iostream"
#include "string"
#include <typeinfo>
using namespace std;

class Zero
{
public:
    virtual void f111() { }
};

class Base : public Zero
{
public:
    virtual void f() { }
};

class Deri1234567890ve : public Base
{
};

typedef unsigned long DWORD;

struct PMD
{
    int mdisp;  //member displacement
    int pdisp;  //vbtable displacement
    int vdisp;  //displacement inside vbtable
};

struct RTTIBaseClassDescriptor
{
    struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class
    DWORD numContainedBases; //number of nested classes following in the Base Class Array
    struct PMD where;        //pointer-to-member displacement info
    DWORD attributes;        //flags, usually 0
};

struct TypeDescriptor
{
    DWORD ptrToVTable;
    DWORD spare;
    char name[ ];
};

struct RTTIClassHierarchyDescriptor
{
    DWORD signature;      //always zero?
    DWORD attributes;     //bit 0 set = multiple inheritance, bit 1 set = virtual inheritance
    DWORD numBaseClasses; //number of classes in pBaseClassArray
    struct RTTIBaseClassArray* pBaseClassArray;
};

struct RTTICompleteObjectLocator

{

    DWORD signature; //always zero ?

    DWORD offset;    //offset of this vtable in the complete class

    DWORD cdOffset;  //constructor displacement offset

    struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the complete class

    //int * ptr;
    struct RTTIClassHierarchyDescriptor* pClassDescriptor; //describes inheritance hierarchy

};

int main()
{
    /*Base *pderive = new Deri1234567890ve();
    int **ptr = (int **)(&pderive);
    int *ptable = (int *)(*(int *)(*ptr));
    int * rtti = ptable -1;

    RTTICompleteObjectLocator * RIIT_locator =   (RTTICompleteObjectLocator *)( *(int*)rtti);
    cout<<RIIT_locator->pTypeDescriptor->name<<endl;*/

    Base *pderive = new Deri1234567890ve();
    int *ptable = (int*)*(int*)pderive;
    int * rtti = ptable -1;

    // 显示当前类的名字“。。Deri1234567890ve。。”    RTTICompleteObjectLocator * RIIT_locator =   (RTTICompleteObjectLocator *)( *(int*)rtti);
    cout<<RIIT_locator->pTypeDescriptor->name<<endl;

    // 显示自己和所有父类的名字    int * p1 = (int*)(RIIT_locator->pClassDescriptor->pBaseClassArray);
    int * p2 = (int*)*(p1+2);
    TypeDescriptor* pDesc = (TypeDescriptor*)(*p2);
    cout<<"One of Base Classes: "<<pDesc->name<<endl;

    p1 = (int*)(RIIT_locator->pClassDescriptor->pBaseClassArray);
    p2 = (int*)*(p1 + 1);
    pDesc = (TypeDescriptor*)(*p2);
    cout<<"One of Base Classes: "<<pDesc->name<<endl;

    p1 = (int*)(RIIT_locator->pClassDescriptor->pBaseClassArray);
    p2 = (int*)*(p1);
    pDesc = (TypeDescriptor*)(*p2);
    cout<<"One of Base Classes: "<<pDesc->name<<endl;
}

参考:

浅议 Dynamic_cast 和 RTTI   http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1971898.html

http://www.openrce.org/articles/full_view/23

asdfasdf

时间: 2024-08-11 09:48:55

dynamic_cast, RTTI, 整理的相关文章

RTTI: dynamic_cast typeid

dynamic_cast:将基类类型的指针向派生类指针安全转换.多用于下行转换.上行转换时,和static_cast是一样的.C++类型转换看这里.下面主要说多态下的RTTI: 使用条件: 基类应有虚函数. 编译器需启用Runtime Type Information/Identification(RTTI),运行时类型信息.VS下在项目属性页下启用,如下,选 是: (VS2013测试:默认的留空不选也能正常使用dynamic_cast) 结果: 对指针进行dynamic_cast,失败返回nu

RTTI之dynamic_cast运算符

#include <iostream> #include <cstdlib> #include <ctime> using std::cout; class Grand { private: int hold; public: Grand(int h=0):hold(h){} virtual void Speak() const {cout << "I am a grand class!\n";} virtual int Value()

浅议 Dynamic_cast 和 RTTI(转)

http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1971898.html http://www.cnblogs.com/jerry19880126/archive/2012/08/14/2638192.html reinterpret_cast// refer to instruction below. http://www.cnblogs.com/ider/archive/2011/07/30/cpp_cast_operator_part3

Google C++ 风格指南内容整理

之前一直没有全面的看过Google C++风格指南,现在很多公司进行C++开发都要求按照Google C++风格.在这个网站 http://zh-google-styleguide.readthedocs.org/en/latest/contents/  有人已经把其翻译成中文.为了便于以后查看,下面的内容完全是来自于这个网站,只是把多个网页的内容整理放在了一起. 1.      头文件: 通常每一个.cc文件都有一个对应的.h文件.也有一些常见例外,如单元测试代码和只包含main()函数的.c

c++中RTTI

RTTI 是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.本文将简略介绍 RTTI 的一些背景知识.描述 RTTI 的概念,并通过具体例子和代码介绍什么时候使用以及如何使用 RTTI:本文还将详细描述两个重要的 RTTI 运算符的使用方法,它们是 typeid 和 dynamic_cast.如何确定对象的动态类型呢?答案是使用内建的 RTTI 中的运算符:typeid 和 dynamic_cast. typeid的

C++的 RTTI 观念和用途(非常详细)

自从1993年Bjarne Stroustrup [注1 ]提出有关C++ 的RTTI功能之建议﹐以及C++的异常处理(exception handling)需要RTTI:最近新推出的C++ 或多或少已提供RTTI. 然而,若不小心使用RTTI,可能会导致软件弹性的降低.本文将介绍RTTI的观念和近况﹐并说明如何善用它. 什么是RTTI﹖      在C++ 环境中﹐头文件(header file) 含有类之定义(class definition)亦即包含有关类的结构资料(representat

C 语言Struct 实现运行类型识别 RTTI

通过RTTI,能够通过基类的指针或引用来检索其所指对象的实际类型.c++通过下面两个操作符提供RTTI. (1)typeid:返回指针或引用所指对象的实际类型. (2)dynamic_cast:将基类类型的指针或引用安全的转换为派生类型的指针或引用. 对于带虚函数的类,在运行时执行RTTI操作符,返回动态类型信息:对于其他类型,在编译时执行RTTI,返回静态类型信息. 当具有基类的指针或引用,但需要执行派生类操作时,需要动态的强制类型转换(dynamic_cast).这种机制的使用容易出错,最好

const_cast,static_cast,dynamic_cast,reinterpret_cast的区别

C++继承了C中的隐式和显式转换的方式.但这种转换并不是安全和严格的, 加上C++本身对象模型的复杂性,C++增加了四个显示转换的关键字.(C++是强类型语言) 经过编码测试,小结如下: const_cast:仅用于去掉完全同类型的const,volatile约束,不能含有任何其它类型的转换,若不含约束也可以相当于没转换static_cast:使用类型可在继承的方向上向上或向下转换,不进行安全检查. 子类转父类,值.引用.指针形式均可,其中指针还可以是常量 父类转子类,值不可以,引用和指针均可,

java的RTTI和反射机制

RTTI,即Run-Time Type Identification,运行时类型识别.它假定我们在编译时已经知道了所有的类型.那么在运行时就能够自动识别每个类型. 很多时候需要进行向上转型,比如Base类派生出Derived类,但是现有的方法只需要将Base对象作为参数,实际传入的则是其派生类的引用.那么RTTI就在此时起到了作用,比如通过RTTI能识别出Derive类是Base的派生类,这样就能够向上转型为Derived.类似的,在用接口作为参数时,向上转型更为常用,RTTI此时能够判断是否可