c++完备的运行时类型信息的示例分析
本篇文章给大家分享的是有关c++ 完备的运行时类型信息的示例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
专注于为中小企业提供网站设计制作、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业白云免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上1000家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
众所周知,码猿写代码,自然要求严谨周密,殊不知想象力也很重要。本座阅码几十年,很是感概很多码猿的脑洞被大大禁锢,鲜有人能越雷池一步,特别是c++的同学,连同委员会的那一坨老头子,都很让人无语至极,出自这些人的作品,都是一个死鱼眼睛样子,千人一面,毫无灵动之生趣可言。stl,boost这些库都是这样子(虽然它们确实可以完成大多数日常任务),更别说其他的库,没有什么让人耳目一新之处。
就说说动态类型信息这块,又或者说是反射。自然,语言本身提供的废物type_info就懒得说了,除了证明c++也东施效颦,也能支持动态信息之外,就别无用处了,有谁会正儿八经的用type_info做点正儿八经的事情呢。因此,各路人马纷纷上阵,都要弥补c++在运行时类型信息上的缺失。因为类型的反射信息实在太重要,或者说,反射的用武之地太多太多,表面上很多事情不需要反射,或者字面代码上就看不到反射的痕迹,但是内里的实现,大把大把的反射在发光发热。c++坚持不在动态信息上给予一点点多余的支持,并不表示c++就不需要反射了,看看标准库这个极力回避动多态的典范,是一个怎样的失败作品,嗯,这个以后再谈吧。假如stl一开始就没有如此大力排斥动多态,你看看就连内存分配的allocator都可以做到静态类型信息里面(最新版的c++终于也要接受多态的allocator,c++界居然一片欢呼鼓舞,真是悲哀),今时今日的c++就不会在很多领域上到处割地求和。
总的来说,现在市面上的c++反射库,都是侵入式,都学着mfc那一套,都是要求继承自一个基类Object,然后才能对外提供反射信息的功能,先不说它们提供的类型信息是否完备,这样子就把用途广泛限制死在一个很窄很窄的小圈子里面了。这些反射库,1、不能反射基本类型,int、char、double、const char*、……等;2、不能反射非继承自Object的class或者struct,3、也不能反射模板类,比如vector
说得具体一点,我们要求的反射库是这样子的。当然,首先要有一个类型信息对象TypeInfo,里面装满了关于对于类型的所有详细信息。如下所示:可以猜到这种反射下框架,只支持单继承,这是故意的。
struct TypeInfo { public: templatevoid ConstructObject(void* obj, MemoryAllocator* alloc, Args&& args)const; bool IsDerviedOf(const TypeInfo* base)const; public: virtual TIType GetTIType()const = 0; virtual const InterfaceMap* GetInterfaces()const; virtual jushort GetMemorySize()const; virtual ConstText GetName() const; virtual AString GetFullName()const; virtual jushort GetAlignSize() const; virtual ConstText GetSpaceName()const; virtual const TypeInfo* GetBaseTypeTI()const; virtual const TypeInfo* GetPointeedTI()const; virtual size_t GetHashCode(const void* obj)const; virtual bool IsValueType()const { return true; } virtual bool IsClass()const { return true; } virtual bool DoInitAllocator(void* obj, MemoryAllocator* memAlloc)const; virtual bool NeedDestruct()const { return false; } virtual void DoDefaultConstruct(void* obj)const; virtual bool CanDefaultConstruct()const { return true; } virtual void DoAssign(void* dest, const void* src)const; virtual bool Equals(const void* objA, const void* objB)const; virtual void DoDestruct(void* obj)const; };
然后,就要有一个函数TypeOf,应该是两个,一个是无参数的类型模板函数,可以这样调用,TypeOf
TypeOf
TypeOf
TypeOf
Object* a = new ObjectA; TypeOf(a) == TypeOf
其实这里面的原理也没什么神奇,无非就是trait配合sfine,接下来就全部都是苦力活,就是为每一种类型都专门特化一个详细描述的类型对象,用宏可以节省大量的代码。但是整个反射库,本座前前后后重构了十几次,现在也还在重构之中,终究还是解决了开发上所遇到的各种事情。比如,序列化(支持指针、支持多态)、对象与xml的互换、对象与json的互换、数据库表读写对象、格式化、Any类型、非侵入式接口、消息发送、字符串生成对象等等。
其实现方式,概括起来,就是引入间接层元函数TypeInfoImp专门用于返回一个类型type,type里面有一个GetTypeInfo()的函数。然后TypeOf调用TypeInfoImp里的type的GetTypeInfo()最终得到TypeInfo对象。代码如下所示。
templatestruct TypeInfoImp { typedef Ty type; static const bool value = THasGetTypeInfoMethod ::value; }; template struct TypeInfoImp : public TypeInfoImp { typedef typename TypeInfoImp ::type type; static const bool value = TypeInfoImp ::value; }; template const TypeInfo* TypeOf() { typedef typename TypeInfoImp ::type TypeInfoProvider; return TypeInfoProvider::GetTypeInfo(); } template const TypeInfo* TypeOf(const Ty& obj) { typedef typename IsRttiType ::type is_rtti; //又是间接层,对动态类型和非动态类型分别处理 return ImpTypeOf(obj, is_rtti()); } template<> struct TypeInfoImp < bool > { static const bool value = true; typedef TypeInfoImp type; static TypeInfo* GetTypeInfo(); }; TypeInfo* TypeInfoImp ::GetTypeInfo() { static TypeInfo* ti = CreateNativeTypeInfo ("bool"); return ti; }
可能可以有简洁的方式,比如不需要引入TypeInfoImp,但是实际最终证明TypeInfoImp的方式最具灵活性也最能节省代码。最起码,它在自定义的struct或者class就很方便,只要改struct内部包含一个GetTypeInfo()的函数,它就可以被纳入TypeOf体系中,非常方便。对于模板类型的TypeInfoImp,就要用到哈希表了。比如,对于std::paira的类型信息,如下实现,
templatestruct TypeInfoImp < std::pair > { static const bool value = true; typedef TypeInfoImp < std::pair > type; static TypeInfo* GetTypeInfo() { ParamsTypeInfo args; return PodPair::LookupTemplateTypeInfo(args); } };
提取其类型参数的const TypeInfo*,生成数组。用此数组到PodPair的哈希表里面查找,如果哈希表中以有此类型数组参数的对象就返回,否则见创建一个添加一条哈希条目,然后返回。每一个泛型类型,比如vector,list,pair都有一个属于自己的哈希表。
打完收工。原理很简单,但是对于工业级的反射库,要考虑很多细节,比如,TypeInfo对象的内存管理;怎么为enum类型生成一堆字符串,以支持字符串和enume值的互相转换;生成并保存class的构造函数和析构函数指针;命名空间的支持;仿真C#里面的attribute;如何以最方便的方式生成成员字段或者成员函数信息等等,一句话,就是他妈的体力活。但是,回报是很丰盛的,这里的苦力活做完之后,程序的其他地方上,基本上,就没有什么重复相似的代码,一切的体力工作全部就可以压在类型信息这里了。
以上就是c++ 完备的运行时类型信息的示例分析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注创新互联行业资讯频道。
分享名称:c++完备的运行时类型信息的示例分析
链接URL:http://pwwzsj.com/article/ggepcd.html