加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 创业 > 正文

C++编写非侵入式接口

发布时间:2021-01-10 08:05:01 所属栏目:创业 来源:网络整理
导读:终于写到c++的非侵入式接口了,欢快,开心,扫兴,脱节,…… 。在搞了这么多的面向工具科普之后,本人也已经开始不耐心,至此,不想做太多叙述。 固然,很早就清晰怎么在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个指针成员字段,且第1个字段必然是目标范例指针,第二是范例信息工具(用于泛型),第三是特殊参数,序次不能乱。成员字段假如不必要用到第二第三个成员字段数据,可以省略不写,比如这里。全部接话柄现类必需遵守这样的内存机关;

3、装配,将接口的实现类装配到现有的类上,以汇报编译器该类对付某个接口(这里为IFormatble)的实现,用的是第2步的实现类ImpIntIFormatble;

PPInterfaceOf(IFormatble,int,ImpIntIFormatble)

4、将实现类注册到范例信息的接话柄现列表中,这一步可以省略,只是为了运行时的接口查询,相等于IUnknown的Query。这一行代码是在全局工具的结构函数中执行的,放在cpp源文件中

RegisterInterfaceImp<IFormatble,int>();

然后就可以开开心心地行使接口了,好比

      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++的强盛,也只能间断了。

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读