C++ RTTI的简单实现(二)

前不久写了个 C++ RTTI的简单实现(一) ,是在查了一些RTTI资料后自己倒腾出来的。近日重看(一两年前看的忘的东西挺多的)《深入浅出MFC》,看到候老师关于MFC六个仿真中的RTTI实现,对比了下自己的设计,下面总结一下。

相同点

整体的宏定义很类似,一个静态变量,一个虚函数返回真实类型。超级父类的特殊处理。

不同点

数据结构
MFC中用的是单链表,采用头插法建立链表。结构体内有三个指针:一个静态头指针,一个next指针,还有一个指向父类的指针。本人用的树形结构。一个父指针,一个兄弟指针,一个孩子指针。我的结构体设计的稍微啰嗦了一些。不过多出来的信息在某些情况下也是有用的,比如可以列出A类的所有派生类,并按照层次列出(觉得有用的可讨论)。
映射表
我的设计中有一张key为类名(字符串),value为类的runtimeclass地址的映射表,以此来定位某类在链表中的位置。MFC中用了头指针来访问链表。这一点不能说我的设计和MFC比没有一点优势,空间换时间嘛,在dynamic_cast的我这种实现会快一些,少一些搜索时间。
细节
在实现链接的时候,MFC用的是结构体的构造函数,我是用的模板函数,本质原因还是数据结构上的差异。另外MFC上的可以实现动态创建。我也进行一下修改,支持动态创建功能。

修改代码支持动态创建

改下结构体

class Shape;
////继承链结构体定义/////
typedef struct tagRTTI_Tree{
    const char *pClassName;//类名
    struct tagRTTI_Tree *pFather;//父亲
    struct tagRTTI_Tree* pChild;//第一个派生类
    struct tagRTTI_Tree* pBrothers;//兄弟类(同一个父亲)
    Shape* (*createObj)();//+ 建构函数 
}RTTI_Tree;

插入构造代码

///构造RTTI ID
#define MY_RTTI(CLASS_NAME) \
public: \
    static RTTI_Tree s_RTTINode; \
    static Shape* CreateObj(){return new CLASS_NAME;} \ //+
    virtual const char * typeID(){return "DUCO|"#CLASS_NAME;} 
//构造继承链 超级父亲
template<class MT>
RTTI_Tree RTTI_Create_Link(const char *pName){
    RTTI_Tree t;
    t.pClassName=pName;
    string str(pName);
    g_RTTI_Map[str]=&(MT::s_RTTINode);
    t.pFather=NULL;
    t.pBrothers=NULL;
    t.pChild=NULL;
    t.createObj=&MT::CreateObj;//+
    return t;
}
`//构造继承链 普通类
template<class MT,class FT>
RTTI_Tree RTTI_Create_Link(const char *pName){
    RTTI_Tree t;
    RTTI_Tree *pCur;
    t.pClassName=pName;//类名
    t.pFather=&(FT::s_RTTINode);//父亲类
    t.pChild=NULL;
    t.pBrothers=NULL;
    t.createObj=&MT::CreateObj;//+
    //父亲信息更新
    if(FT::s_RTTINode.pChild==NULL)//第一个孩子
        FT::s_RTTINode.pChild=&(MT::s_RTTINode);
    else{
        pCur=FT::s_RTTINode.pChild;
        while (pCur->pBrothers)//找到最后一个孩子
            pCur=pCur->pBrothers;
        pCur->pBrothers=&(MT::s_RTTINode);
    }
    //映射表,索引整棵树
    string str(pName);
    g_RTTI_Map[str]=&(MT::s_RTTINode);
    return t;
}

测试

Shape* Load(const char *str){
     RTTI_Tree *createObj=g_RTTI_Map[str];
     if(createObj==NULL){
        return NULL;
    }else{
        Shape *p1=createObj->createObj();
        return p1;
    }
}
int main(){
    //获取真实类型
    Shape *s1,*s2,*s3;
    s1=new Shape();
    s2=new Circle();
    s3=new RedRect();
    cout<<s1->typeID()<<endl;// DUCO|Shape
    cout<<s2->typeID()<<endl;// DUCO|Circle
    ///动态造型
    auto *t1=my_dynamic_cast<Circle,Shape>(s1);//实际内容为Shape想转为CirCle 
    cout<<(int*)t1<<endl;//NULL
    auto *t2=my_dynamic_cast<Circle,Shape>(s2);//实际内容为CirCle想转为CirCle 
    cout<<(int*)t2<<endl;//SUCCESS
    auto *t3=my_dynamic_cast<Rect,Shape>(s2);//实际内容为CirCle想转为Rect(兄弟) 
    cout<<(int*)t3<<endl;//NULL
    auto *t4=my_dynamic_cast<Rect,Shape>(s3);//实际内容为RedRect想转为Rect(直系) 
    cout<<(int*)t4<<endl;//SUCCESS
    auto *t5=my_dynamic_cast<Circle,Shape>(s3);//实际内容为RedRect想转为Circle(非直系) 
    cout<<(int*)t5<<endl;//NULL
    //动态创建
    Shape* c1=Load("DUCO|Circle");
    Shape* c2=Load("DUCO|keke");
    if(c1)
        cout<<c1->typeID()<<endl;//DUCO|Circle
    if(c2)//NULL
        cout<<c2->typeID()<<endl;
    getchar();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值