当前位置:网站首页 > 技术博客 > 正文

c++接口类型



@

最近在工作中,需要将代码封装成库,供其他方调用。在其中涉及到如何设计接口类,第一次接触,将总结和经验记录下来。

为什么本文叫做《工程实践:C++的接口设计》,是因为,我们大部分人入门的时候,都是调用别人封装好的库函数,却没有尝试过自己封装库给别人用。但是在正常工作中,也就是工程化中,我们会经常封装库给其他人应用,这里面会涉及到怎么封装一个函数,提供一个优秀的接口。
接口:类暴露出来的部分,是类所提供的功能。

我们在工程化的过程中,设计接口一般遵守以下几个准则:

  1. 单一功能原则
    一个class就其整体应该只提供单一的服务。如果一个class提供多样的服务,那么就应该把它拆分,反之,如果一个在概念上单一的功能却由几个class负责,这几个class应该合并。
  2. 开放/封闭原则
    一个设计并实现好的class,应该对扩充的动作开放,而对修改的动作封闭。也就是说,这个class应该是允许扩充的,但不允许修改。如果需要功能上的扩充,一般来说应该通过添加新类实现,而不是修改原类的代码。添加新类不单可以通过直接继承,也可以通过组合。
  3. 最小惊讶原理
    在重载函数,或者子类实现父类虚函数时,应该基本维持函数原来所期望的功能。
  1. 过度封装
    很多人喜欢这样封装,把接口局限在仅仅解决一个特定的问题上面,失去了代码的灵活性。而且,也容易出现面条代码,让人不知所云。一个接口被写的仅仅用于解决当前问题,当试图增加其扩展性时,发现为时已晚。
    为了防止过度封装,在设计接口的时候,我们应该考虑以下几个问题:

1.我们需要解决什么问题
2.问题的核心是什么
3.应该怎样设计,可以方便客户程序员扩展

  1. 起名要见名知意
    一个好的的接口方法名,是接口设计中成功的一半。
  2. 不要让使用者进行过多工作
    如果使用者使用我们的接口时,进行了过多的准备,那么对我们来说就是失败的。
    所以,设计的时候要记得尽可能简化客户程序员逻辑,使接口设计能够看起来简洁、漂亮,而不至于被接口的复杂性所吓倒。
  3. 简洁
    这个比较好理解,举个例子,你一定见过一个函数使用,需要传进去五六个参数,但是对我们有用的往往只有那么一俩个。
    所以,简洁设计是接口设计的一个重要原则。可以在接口的内部实现中,使用复杂冗余的参数,而在暴露给客户程序员的接口中,一定要尽可能简洁。
  4. 清晰的文档表述
    这也是我在工作中,最头疼的问题,头疼的不是我不会写,而是在使用其他人提供的库时,没有使用文档,使用起来是痛苦的,所以为了不让这种痛苦发生在其他人身上,我现在从维护一份良好的文档开始。

隔离用户操作与底层逻辑

一般来说,有两种方法设计接口类。
第一种是PIMP方法,即Pointer to Implementation,在接口类成员中包含一个指向实现类的指针,这样可以最大限度的做到接口和实现分离的原则。
第二种方法叫Object-Interface方法,它的思想是采用C++的动态功能,实现类继承接口类,功能接口函数定义成虚函数。

先说结论,我们处于自身习惯的原因,选择了Object-Interface方法。

所谓PImp是非常常见的隐藏真实数据成员的技巧,核心思路就是用另一个类包装了所要隐藏的真实成员,在接口类中保存这个类的指针。

 

在接口文件中声明一个ComplexImpl*,然后在另一个头文件compleximpl.h中定义这个类

 

可以发现,这个ComplexImpl的接口基本没有什么变化(其实只是因为这个类功能太简单,在复杂的类里面,是需要很多private的内部函数去抽象出更多实现细节),然后在complex.cpp中,只要

 

包含了ComplexImpl的实现,那么所有对于Complex的实现都可以通过ComplexImpl这个中介去操作。详细做法百度还有一大堆,就不细说了。

一般来说,如果一个接口类对应有若干个实现类,可以采用这种方法。

上面我们讲了plmp方法,我们隐藏掉俩个数据成员,但同时也多出了一个新的数据成员,也就是接口指针,那么有没有方法,连这个指针也不要呢?

这时候就是抽象基类发挥作用的时候了。看代码:

 

将要暴露出去的接口都设置为纯虚函数,通过 工厂方法Create来获取Complex指针,Create返回的是继承实现了集体功能的内部类;

 

至于Create函数也很简单:

 

这样,我们完完全全将Complex类的实现细节全部封装隐藏起来了,用户一点都不知道里面的数据结构是什么;

当然,对于Complex这样的类来说,用户是有获取他的实部虚部这样的需求的,也很简单,再加上两个Get方法就可以达到目的。

  1. 首先,声明一个接口
 
  1. 通过继承的方式实现这个接口
 
 
  1. 最后,通过管理类创建接口派生类的实例,或者销毁接口派生类的实例:
 
 

现在我们接口已经实现完毕了,我们可以把它封装成库,给其他人使用了,这里封装库我们就不多言了。

最后,来看一下使用效果:

 

以上代码只提供给外部circle的接口,circle的实现完全被隐藏了起来,外部将无从知晓,外部使用者只能通过circle管理类生成circle的派生类的实例。外部使用者得到circle派生类的实例后,除了能调用接口暴露的方法area()外,其它什么也做不了,这样就完全达到了使用接口的最终目标。

C++中的接口设计准则
C++ 头文件接口设计浅谈
一款优秀的 SDK 接口设计十大原则
C++:如何正确的使用接口类

本篇文章抛砖引玉,自己也是刚刚接触,写完收工,干饭去!

  • 上一篇: ddm 公式
  • 下一篇: 武汉网络dns地址
  • 版权声明


    相关文章:

  • ddm 公式2025-05-05 13:01:04
  • 笔记本电脑键盘对应快捷键2025-05-05 13:01:04
  • springboot集成sso2025-05-05 13:01:04
  • 自己的小程序appid在哪里看2025-05-05 13:01:04
  • gif录制编辑工具2025-05-05 13:01:04
  • 武汉网络dns地址2025-05-05 13:01:04
  • 函数已有主体是什么意思2025-05-05 13:01:04
  • 江苏工匠企业管理有限公司2025-05-05 13:01:04
  • java线程用法2025-05-05 13:01:04
  • 串口调试器sscom2025-05-05 13:01:04