当前位置: 代码网 > it编程>编程语言>C/C++ > C++接口设计怎么做?从函数到分布式全面解析

C++接口设计怎么做?从函数到分布式全面解析

2026年08月31日 C/C++ 我要评论
一、接口接口,在前面已经分析了几篇相关的文章了。但具体到c++如何实践开发,则需要在本文再唠叨几句。接口的定义和作用,对于绝大数的开发者来说,应该已经门儿清,这里就不再重复,不清楚的可以查看前面的相关

一、接口

接口,在前面已经分析了几篇相关的文章了。但具体到c++如何实践开发,则需要在本文再唠叨几句。接口的定义和作用,对于绝大数的开发者来说,应该已经门儿清,这里就不再重复,不清楚的可以查看前面的相关文章。

在c++的开发实践中,只要程序稍微大一些,就不可避免的要有接口的处理。它对于模块的安全性、复用性非常重要。同时,对于大规模的软件开发来说,分层和跨域的接口设计更是重中之重。

在设计中,接口是分层和模块间解耦的重要实现手段。相同的接口,因为应用的场景不同,可能有不同的实现。它们有可能依赖于版本的控制也有可能基于自动反射的控制等等。这也解决了对外封闭,对内灵活的的处理机制。

二、种类

接口的形式上的本质是什么?其实就是函数。无论是专门接口函数,还是暴露出来的抽象的接口类型(包括语言专有的接口定义以及类似c++这种以抽象类或其它形式提供接口),其内部真正操作的仍然是函数。

即从形式上的表现来看,主要分为两大类,即函数和抽象类型。

对于c++来说,实现接口的细分方式有很多种方式:

1.函数

这是接口最常见的形式,它不但包括普通的函数,也包括模板函数、抽象函数、回调函数、函数指针以及lambda表达式等

 using cbfunc = void (*)(int);

2.类

这在于内部接口的实现中较为常见,一般是通过抽象类来实现类似于其它语言的interface。当然,有的也可以提供普通类或结构体来实现接口。比如前面提到的不同通信协议下的数据协议的实现

  class iaction {
     public:
         virtual double play() const = 0;
         virtual ~iaction() = default;
  };
  struct data1
  {
     int d;
  };
  struct data2:public data1{};

3.模板

这种实现和类、函数一致,只是抽象的形式改为了模板泛型。更加容易适配较为广泛的开发和应用。这里就不再给出具体的例子

4.新标准中的concepts等

这种属于一种设计型的接口控制,包括前面的sfinae等一些特定的用法等

 template<class t>
 concept checkdemo = requires(t t) {
    t.must();
};

三、数据传输协议和格式

之所以把这节专门列出,主要是面对库、框架或分布式的设计者。

普通的接口应用往往用到的较少或者说不建议盲目的引入:

  1. c++的对象
    在这种接口的数据处理中,往往使用各种对象如容器、tuple以及继承对象等等
  2. 常见的数据格式
    常见的数据格式有xml、yaml、json以及二进制的框架格式如protobuf、messagepack及avro等
  3. 常见的数据协议
    常见的协议包括restful、grpc、websocket、soap和graphql等等

这个不是重点,所以就不再一一展开说明,有兴趣可以自行查看,都是比较成熟的技术。

三、c++中设计实践

在前面的分析中,更强调的是接口的规范性和实现的方式,但缺少了对其整体的考虑:

1.接口

对于接口的设计,场景有很多种情况,但需要注意的千万不能教条或僵化的套用相关的接口设计方法。常见的接口应用场景有以下几种情况:

自己应用:这种相对灵活,哪种方式就看实现的方便、快捷程度

对内应用:这就需要考虑一定的适配性和升级的扩展,但仍然看重快捷方便

对外应用:重点考虑的是适用性,特别是作为底层支持时,更应该考虑各种场景下的可用性

强制接口应用:这种就是调用或指定对某些应用提供接口服务,需要严格对齐需求。其次才能考虑方便快捷以及扩展性等

跨平台(语言)应用:这种更应该考虑的是抽象平台和语言的兼容性。不要引入对平台或语言耦合性的技术点和数据类型

2.参数和返回值

这是接口中重要的一环,看上去简单,但如果对外开放或跨平台支持时,就需要仔细斟酌。

比如参数的类型、数量。返回值的类型。参数的顺序有没有依赖等等

3.数据协议或格式

在传统接口设计中,对数据传输是十分敏感的。如字节序、对齐等等。但随着互联网应用的发展,如json,xml以及其它各种数据格式或封装都涌现出来。这时就考验设计者如何在效率、成本、安全等方面上的综合考虑了。比如为了一个简单的字符串传递引入了json,又需要引入相关的解析库,是不是值得?未来是不是需要更多的使用json等等

可以这样理解,接口的设计要根据场景和实际需求的变化,不断的进行调整。而不是简单的认为因袭传统或书本上怎么教就怎么做。灵活是c++的灵魂!接口设计亦是如此。

四、分析

在明白了接口及其设计的复杂性之后,就可以有针对性的学习别人设计思想来完善自己的设计思想。

一般来说,对开发者经常遇到的接口有三种情况:

  1. 简单的函数接口
    这种简单的函数接口,更强调的是一种显式的约束。让应用者能够以类似“防呆”的调用进行应用
  2. 开发框架和库的接口
    这种对框架和库的接口设计,除了上面的约束外,还需要考虑对支持的平台、语言等进行兼容性设计以及异常情况的反馈。它的接口抽象可能更高级,适配性更强。可以引入更多的设计方式如注入等。在框架中往往还会引入异步接口这种形式。
  3. 分布式接口
    它更强调的是“契约”。往往这种接口是建立在某种广泛的协议或通信框架基础上。对异构平台、不同系统等进行管理。接口形式上更贴近于常见的协议类型如restful等

从不同的角度看接口的设计和应用,必然呈现出不同的感官情况。这也是一个正常的应用形态。这也意味着,即使相同的设计方式,达到的目的不同,可能引入的侧重点也有所不同。

接口的适配

在实际的开发中,往往会遇到接口是较为抽象的(低级的),而c++中使用的相对要高级一些。这就需要对不同的应用进行接口的适配。隔离变化并适配使用。

一般接口的适配有以下几种方式:

  1. 使用仿函数
    这是一种最简单的方式,通过重载operator(),将对象操作转为函数操作。它适合逻辑性强、比较简单的场景下
  2. 使用设计模式
    经典的就是适配器模式,也可以使用策略模式的装饰器模式等等。看具体的情况。
  3. 使用模板
    模板提供了各种特化、偏特化和全实例化。从而实现不同情况下的类型适配

其实到这里,大家是不是发现,设计本身就是要对开发有相当深入的理解,否则设计一定是一个“受限”的实现。说直白一些,猪都没见过,怎么可能画出猪来。

五、关注性能

回到c++的特性之一,性能。接口设计或适配很多情况下是为了双方的通信或数据处理,所以接口设计的好坏,很有可能影响要通信的效率和数据处理的速度。甚至可能影响到接口应用方的设计架构。

举一个简单的例子,接口中有一个大的对象或字符串,此时不使用引用,可能就会影响到效率。

所以在接口设计时需要考虑:

  1. 拷贝的消除
    这个很好理解,不要进行无谓的大对象或大内存的拷贝
  2. 消除动态内存的分配
    有些接口设计或适配可能需要进行动态内存的分配,比如使用了多态。这
  3. 消除中间环节调用
    不要在设计或适配过程中加深函数的调用栈,虽然大多数情况下可能影响很小
  4. 允许的情况下使用内联
    使用内联应该都明白,强调的还是速度
  5. 编译期预处理
    把一些能够在编译期进行展开或计算的代码转移到编译期,在模板编译或元编程中是一种重要的优化手段

六、总结

接口非常常见,也很容易设计。可面临的场景复杂、应用各异时,对设计者的要求就相当高了。

大家可以看一下linux内核中相同接口的发展变化,从不同的角度来看为什么这个接口会如此变化?可能是采用了新技术,也可能是精简是功能…凡此种种。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com