C++编写非侵入式接口
终于写到c++的非侵入式接口了,欢快,开心,扫兴,脱节,…… 。在搞了这么多的面向工具科普之后,本人也已经开始不耐心,至此,不想做太多叙述。 固然,很早就清晰怎么在c++下搞非侵入式接口,可是,整个框架代码,重构了十屡次之后,才终于满足。支持给根基范例添加接口,比如int,char,const char*,double;支持泛型,比如vector,list;支持担任,基类实现的接口,暗示子类也担任了对该接口的实现,并且子类也可以拒绝基类的接口,比如鸭子拒绝基类鸟类“会飞”,编译时报错;支持接口组合;……,可是,这里仅仅简朴先容其道理,并不涉及C++中各类失常细节的处理赏罚,C++中,但往往要正儿八经的轻微做点正事,就要面对无限无尽的细节纠结。 先看看其行使例子: 1、天然是界说一个接口:取之于真实代码片断 struct IFormatble { static TypeInfo* GetTypeInfo(); virtual void Format(TextWriter& stream,const FormatInfo& info) = 0; virtual bool Parse(TextReader& stream,const FormatInfo& info) { PPNotImplement(); } }; 2、接口的实现类,假设为int添加IFormatble的接话柄现,现实代码必定不会这样对一个一个的根基范例来写实现类的代码。这里只是为了举例声名。类的名字就任意起好啦, struct ImpIntIFormatble : IFormatble { int* mThis; //这一行是要害 virtual void Format(TextWriter& stream,const FormatInfo& info)override {} virtual bool Parse(TextReader& stream,const FormatInfo& info)override {} };
3、装配,将接口的实现类装配到现有的类上,以汇报编译器该类对付某个接口(这里为IFormatble)的实现,用的是第2步的实现类ImpIntIFormatble;
4、将实现类注册到范例信息的接话柄现列表中,这一步可以省略,只是为了运行时的接口查询,相等于IUnknown的Query。这一行代码是在全局工具的结构函数中执行的,放在cpp源文件中
然后就可以开开心心地行使接口了,好比 int aa = 20; TextWriter stream(); FormatInfo info(); TInterface<IFormatble> formatable(aa); //TInterface这个名字过丢脸,也没步伐了 formatable->Format(stream,info); double dd = 3.14; formatable = TInterface<IFormatble>(dd); //假设double也实现IFormatble formatable->Format(stream,info); 是否有点神奇呢?着实也没什么,不外就是在trait和内存机关上做文章,也就只是用了范例运算的技巧。考查ImpIntIFormatble的内存机关,对付广泛的c++编译器来说,工具的虚函数表指针(假如存在的话),都放在工具的起始地点上,后头紧跟工具自己的成员数据字段,因此,ImpIntIFormatble的内存机关相等于, struct ImpIntIFormatble { void* vtbl; int* mThis; }; 留意,这里已经没有担任了。这就是,实现了IFormatble 接口的ImpIntIFormatble工具的内存暗示。因此,可以想象,全部的接话柄现类的内存机关都逼迫划定为以下情势: struct InterfaceLayout { const void* mVtbl; const void* mThis; //工具自己 const TypeInfo* mTypeInfo; //范例信息 const void* mParam; //增补参数,一样平常很罕用到 }; 虽然,假如编译器的虚函数表指针不放在工具起始地点的话,就没法这么玩了,那么非侵入式接口也无从做起。然后,就是TInterface了,担任于InterfaceLayout template<typename IT> struct TInterface : public InterfaceLayout { typedef IT interface_type; static_assert(is_abstract<IT>::value,"interface must have pure function"); static_assert(sizeof(IT) == sizeof(void*),"Can't have data"); public: interface_type* operator->()const { interface_type* result = (interface_type*)(void*)this; return result; } }; 不管怎么说都好,TInterface工具的内存机关与接话柄现类的内存机关同等。因此操纵符->重载函数才可以粗暴的范例转换来顺遂完成。然后结构TInterface工具的时辰就是逼迫获取ImpIntIFormatble工具的虚函数表(也就是其起始地点的指针数据)指针赋值给InterfaceLayout的mVtbl,进而依次把现实工具的指针放在mThis上,获取到范例信息工具放在mTypeInfo中,假若有须要搭理mParam,也响应地赋值。 然后,就是template<typename Interface,typename Object>struct InterfaceOf各类特化的运用罢了,就不值一提了。 因为c++的abi没有同一尺度,而且,c++尺度也没有划定编译器必需用虚函数表来实现多态,以是,这里的奇技淫巧并不能担保在全部平台上都可以或许创立,可是,非侵入式接口真是利便,已经是本座写c++代码的焦点器材,统统都环绕着非侵入式接口来睁开。 本来规划长篇大论,也只有草草收场。之后,本座就解放了,会暂且分开cppblog好久,打算中的内容,动静发送,虚模板函数,字符串,输入输出,名目化,序列化, locale,全局变量,模板表达式,组合子理会器,allocator,智能指针,措施运行时,抽象工场会见者等模式的另类实现,以求从全新的角度上来示意C++的强盛,也只能间断了。 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |