《C++API设计》阅读笔记1

2023-11-06

1 API简介

  1. API(Application Programing Interface)提供了对某个问题的抽象,以及客户与解决改问题的软件组件之间进行交互的方式。组件本身通常以软件类库形式分发,它们可以在多个应用程序中使用。概括说,API定义了一些可复用的模块,使得各个模块化功能可以嵌入到最终用户的应用程序中去。 API是一个明确定义的接口,可以为其他软件提供特定服务。

  2. C++API通常会包含如下的元素:
    头文件:一组.h头文件,头文件定义了接口,使得客户端代码能够针对该接口进行编译 开源API还包括API实现的源代码即.cpp文件
    **类库:**一个或者多个静态库或者动态库文件,它们提供了API的具体实现 客户端把代码和这些库文件进行链接,从而为应用程序添加相应功能
    **文档:**使用API的概述信息

在C++中,API一般包括一个或多个头文件(.h)以及辅助文档。某个特定API的具体实现通常是可以被链接到最终用户程序中的库文件,它也可以是静态库,又或者是动态库。

  1. SDK与API:
    SDK(软件开发工具包)和术语API是密切相关的。本质上讲,SDK是安装在计算机上的特定平台的包,其目的是使用一个或多个API构建应用。SDK至少要包含编译程序所需的头文件(.h)以及提供API实现的库文件(.dylib、.so、.dll),用以链接到应用程序之中。然而,SDK还可能包含其它帮助使用API的资源,如文档、示例代码以及支持工具。

可以把SDK想象成一个虚拟的程序包,在这个程序包中有一个做好的软件功能,这和程序包有一个接口可以被调用,这个接口就是API

  1. 文件格式和网络协议
    在计算机应用中存在几个其它形式的常用通信”协议”,其中最常见的一个就是文件格式。它是使用众所周知的数据组织层次将内存中的数据存储到磁盘文件上的方法。有了数据文件的格式,任何程序都能读写这种格式的图像文件。这就使得不同用户之间可以交换图像数据

在客户端/服务端应用、点对点应用以及中间件服务,使用建立好的且通常基于网络套接字的协议发送和接收数据。

每当创建一个文件格式或者客户端/服务器协议时,同时也要为其创建API。这样,规范的细节以及未来的任何变更都将是集中且隐藏的。

2 特征——优秀的API应该具有哪些特征

  1. 问题域建模:编写API的目的是解决特定的问题或完成具体的任务; API应该对它所解决的问题提供逻辑抽象, 当你把API文档提供给一位非程序员时,他应当能够理解接口中的概念并且知道它的工作机制; 对问题域的关键对象建模, 该过程旨在描述特定问题域中对象的层次结构,因此经常被称作”面向对象设计”或者”对象建模”。对象建模的目的是确定主要对象的集合,这些对象提供的操作以及对象之间的关系。

  2. 隐藏实现细节:创建API的主要原因是隐藏所有的实现细节,以免将来修改API对已有客户造成影响。任何内部实现细节(那些很可能变更的部分)必须对该API的客户隐藏。主要有两种技巧可以达到此目标:物理隐藏和逻辑隐藏。物理隐藏表示只是不让用户获得私有源代码。逻辑隐藏则需要使用语言特性限制用户访问API的某些元素。
    物理隐藏:在C和C++中,声明只是告诉编译器一个名字以及它的类型,并不为其分配任何内存;而定义提供了类型结构体的细节,如果是变量则为其分配内存;声明告诉编译器某个标识符的名称以及类型,定义提供该标识符的完整细节 物理隐藏表示将内部细节(.cpp)与公有接口(.h)分离,存储在不同的文件中
    逻辑隐藏:封装提供了限制访问对象成员的机制:public、protected、private。封装是将API的公有接口与底层实现分离的过程。逻辑隐藏指的是使用C++语言中受保护的和私有的访问控制特性从而限制访问内部细节。类的数据成员应该始终声明为私有的,而不是公有的或受保护的。
    永远不要返回私有数据成员的非const指针或引用,这样会破坏封装性

    强烈建议在API中采用Pimpl惯用法,这样就可以将所有实现细节完全和公有头文件分开。
    Pimpl惯用法:它将所有的私有数据成员隔离到一个.cpp文件中独立实现的类或结构体中。之后,.h文件仅需要包含指向该类实例的不透明指针(opaque pointer)即可。
    如果不用pimpl,至少也要将头文件内不需要的私有方法移到.cpp中,并将它们转换为静态函数。不要将其作为私有方法暴露在公开的头文件中

    隐藏实现类:除了隐藏类的内部方法和变量之外,还应该尽力隐藏那些纯粹是实现细节的类。实际上,一些类仅用于实现,因此应该将其从API的公有接口中移除。

  3. 最小完备性:尽量简洁
    谨慎添加虚函数: 虚函数的调用必须在运行时查询虚函数表决定,而普通的非虚函数的调用在编译时就能确定。使用虚函数一般需要维护指向虚函数表的指针,进而增加了对象的大小。另外,不是所有的虚函数都能内敛,因而将虚函数声明为内联是没有任何意义的。因为虚函数是运行时确定的,而内联是在编译时进行优化的,且C++中inline只是一个提示,不一定优化的;如果类中包含任一虚函数,那么必须将析构函数声明为虚函数,这样类才能释放其他可能申请的额外资源。绝对不要在构造函数或析构函数中调用虚函数,这些调用不会指向子类

  4. 易用性
    1 正交:API之间互不影响
    2 使用智能指针返回动态申请的对象使得资源分配更见状
    3 使用一致的函数命名和参数顺序
    4 不要将平台相关的#if或#ifdef语句放在公共的API中,因为这些语句暴露了实现细节,并使API因平台而异 P43

  5. 松耦合
    1 除非确实需要#include类的完整定义,否则应该为类使用前置声明。如果类**A仅需要知道类B的名字,即它不需要知道类B的大小或调用类B的任何方法,**那么类A就不需要依赖类B的完整声明。在这种情况下,可以为类B使用前置声明,而非包含整个接口,这样就降低了这两个类之间的耦合 (就是前置只写class B;就好,不需要#include “B.h”)
    2 回调:在C和C++中,回调是模块A中的一个函数指针,该指针被传递给模块B,这样B就能在合适的时候调用A中的函数。模块B对模块A一无所知,并且对模块A不存在”包含”(include)或者”链接”(link)依赖。回调的这种特性使得低层代码能够执行与其不能有依赖关系的高层代码。因此,在大型项目中,回调是一种用于打破循环依赖的常用技术。p51

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

《C++API设计》阅读笔记1 的相关文章

  • 具有相同参数类型但具有不同常量限定符的 std::vector 的转换

    问题很简单 静态转换 或其他一些转换 通常是安全的 std vector lt Foo gt to std vector lt const Foo gt 就二进制而言 我不明白为什么本机类型会有所不同 毕竟const是一种语言约束 不应影响
  • 为什么我会收到未找到分析器的警告?

    我创建了一个玩具项目来检查最新的 NET 7 预览版 5 和正则表达式代码生成 它效果很好 所以我对现有项目应用了相同的更改 不是为了生产 而是为了个人生产力 由于某种原因 我收到这些警告 CS8032 An instance of ana
  • 生成多个随机数

    我想生成 25 个唯一的随机数并将它们列在控制台中 数字的长度应至少为 10 个字符 有什么简单的方法可以做到这一点吗 尝试将数字构建为字符串 并使用 HashSet 确保它们是唯一的 Random random new Random Ha
  • 深拷贝和动态转换 unique_ptr

    假设我有一个如下所示的类 class A virtual A class B public A class C public A 我还有一个 unique ptr 向量 它是这样声明的 std vector
  • 将字符串作为 PChar 从 CSharp 传递到 Delphi DLL

    我正在尝试将字符串从 C 传递到 Delphi 构建的 DLL Delphi DLL 需要 PChar 这是Delphi导出 procedure DLL Message Location PChar AIntValue integer st
  • 使用 C# 将多个音频样本混合到单个文件中

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个能够创建音频文件 mp3 或 wav 的库 NAudio http www codeple
  • Dapper 在执行时挂起

    我有一个 IDb连接 sql UPDATE 表名 SET json json lastupdate SYSDATE WHERE id id var param new DynamicParameters param Add json jso
  • 将 dataGridView 中选定的行作为对象检索

    我有一堂这样的课 public partial class AdressBokPerson public long Session get set public string F rnamn get set public string Ef
  • 组合框下拉位置

    我有一个最大化的表单 其中包含 500px 的组合框控件 停靠在右上角 Width 尝试打开组合框后 列表的一半超出了屏幕 如何强制列表显示在表单中 棘手的问题 我找不到解决这个问题的好办法 只是一个解决方法 添加一个新类并粘贴如下所示的代
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • 您对“大规模 C++ 软件设计”的看法 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 正在阅读亚马逊评论 https rads stackoverflow com amzn click com 0201633620 and ACC
  • C#:自定义转换为值类型

    是否可以将自定义类转换为值类型 这是一个例子 var x new Foo var y int x Does not compile 是否有可能实现上述情况 我需要超载一些东西吗Foo 您将必须重载强制转换运算符 public class F
  • valgrind 在 Raspberry Pi 上返回未处理的指令

    我最近一直在尝试在运行 Debian GNU Linux7 0 喘息 的树莓派 型号 b 上使用 valgrind 来调试分段错误 每次我在编译的 C 程序上运行 valgrind 时 都会得到类似以下内容的信息 disInstr arm
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 使用多态对象数组进行 JSON 反序列化

    我在涉及多态对象数组的 JSON 反序列化方面遇到问题 我已经尝试过记录的序列化解决方案here https stackoverflow com questions 5186973 json serialization of array w
  • 从脚本启用/禁用 GameObject 组件 [Unity3D]

    我需要获取一个脚本中设置的布尔值 放入名为 bouclier 的变量 以启用或禁用游戏对象 该变量位于游戏对象 Player 中 此处右下角 我需要启用或禁用这个游戏对象 Bouclier01 为此 我将脚本附加到游戏对象 Bouclier
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加
  • 实体框架代码首次日期字段创建

    我正在使用实体框架代码优先方法来创建我的数据库表 下面的代码 创建一个DATETIME数据库中的列 但我想创建一个DATE柱子 DataType DataType Date DisplayFormatAttribute ApplyForma
  • 将一个 IEnumerable 拆分为多个 IEnumerable

    我是 linq 新手 我需要根据指示器将 Couple string text bool Indicator 类型的 IEnumerable 拆分为多个 IEnumerable 我尝试使用skipWhile 和 TakeWhile 但没有找

随机推荐

  • 微信小程序从入坑到放弃二十:生成海报前使用wx.downloadFile或wx.getImageInfo时潜在的坑

    摘要 上周六下午16点左右 公司研发群中扔来一张bug截图 当天21点 群里又扔来bug截图 研发团队二话不说开始查找bug如何复现 22点20分左右 我终于复现了bug 随后就是看源码 搜索 跳坑 爬坑 周日同其他研发小伙伴一样 又是奉献
  • OpenCv案例(九): 基于OpenCvSharp图像分割提取目标区域和定位

    以下原图中 物体连靠在一起 目的是将其分割开 再提取轮廓和定位 原图 最终效果 麻烦的地方是 分割开右下角部分 两个连在一起的目标物体 下图所示 基本方法 BoxFilter滤波 二值化 轮廓提取 凸包检测 图像的矩 代码如下
  • Jar包反编译后修改源码再编译

    Jar包反编译后修改源码再编译 文章目录 Jar包反编译后修改源码再编译 1 场景 2 详细步骤 2 1 查看源码 2 2 生成源文件 2 3 构建项目 2 4 编译成jar包 3 参考链接 1 场景 需要对当前的jar包功能进行修改 但是
  • angularjs系列之轻松使用$q进行异步编程

    angularjs系列之轻松使用 q进行异步编程 来源 网络 编辑 admin 第一部分关于js中的异步编程 异步编程简单的说就是你写了一段代码 但他不会按照你书写代码的顺序立即执行 而是等到程序中发生了某个事件 如用户点击了某个按钮 某个
  • 深入理解计算机系统-链接篇

    在linux系统下 很多开源C C 程序的编译规则都是以makefile文件的形式给出 我刚开始学习makefile规则是看陈浩的 跟我一起学makefile 后来看 深入理解计算机系统 这本书 对编译链接有了更加深入的了解 本文主要介绍程
  • 人机交互知识点总结

    人机交互知识点总结 考试题型及分值分布 选择题 10题 20分 填空题 10题 20分 判断题 可选 5题 10分 解答题 5 6题 30分 分析计算题 1 2题 20分 注意 答案有多条时 用1 2 3形式分别列出 考查内容 掌握人机交互
  • CTF加密解密—CRYPTO—密码学签到

    0x00 考察知识点 考虑字符串倒序的问题 0x01 题目 密文是 wohs ftc galf 0x02 Write Up 直接进行字符串倒序即可 签到题 简单点是肯定的啦
  • 操作系统文件的两种结构

    文件 文件指的是一组带标识的逻辑上有完整意义的数据项 构成文件内容的基本单元 的序列 或者是相关联记录的集合 文件存放在磁盘或磁带等存储介质上 文件的逻辑结构和物理结构 一 逻辑结构 1 无结构文件 流式文件 2 有结构文件 记录式文件 二
  • avue crud-tree介绍

    前言 最近遇到了需要使用表格树的需求 发现avue crud有tree的组件 然后在使用过程中发现诸多问题 网上对应的介绍也很少 所以在自己使用成功之后为后人提供帮助 正文 效果图 html部分
  • SOLID Principles in Unity

    什么是SOLID 假如你是一个程序员 我敢肯定你听过编程原则或类似的东西 也许松耦合的设计 SOLID不是一个编程语言或编程范式 它不是一个特定的设计模式 它不是针对某个项目的 在面向对象编程中 SOLID实际上是一个助记缩写五个 S O
  • VMware-报错:无法将Ethernet0连接到虚拟网络VMnet8

    by 小世界 http redcisco blog 163 com 版本 vmware10 0 0 物理机 win8 虚拟机 rhel6 3 问题 无法将 Ethernet0 连接到虚拟网络 VMnet8 有关更多信息 请参见 vmware
  • react-native-image-picker 4.0 集成

    github react native image picker 4 x相对于 2 x 3 x已删除 showImagePicker 4 x相对于 2 x 3 x已删除 showImagePicker 4 x相对于 2 x 3 x已删除 s
  • 【Linux下Docker安装JupterLab】

    Linux下Docker安装JupterLab 拉取docker镜像 docker pull jupyter base notebook latest https jupyter docker stacks readthedocs io e
  • cicd 02--构建通用的CD流程

    cicd 02 构建通用的CD流程 1 介绍 2 CD 构建过程 2 1 参数配置说明 2 2 pipeline 脚本 2 3 测试流程 3 注意事项 4 说明 1 介绍 笔者在 cicd 01 构建通用的CI流程 中介绍了一个通用的doc
  • 简单分析 C 语言的 qsort() 源码

    简单分析 C 语言的 qsort 源码 stdlib h 是使用 C 语言需要引入的库 在系统文件下可以搜索到这个文件夹 在里面可以看到有一个 qsort 文件用编译器或者记事本打开就能看到里面的源码了 单从文件名看 qsort 采用的是快
  • unity ScriptableObject

    ScriptableObject代替单例 和单例一样 在内存是独一份的 是可以被不同的东西读取 需要一些工具链配合 结构是这样的 startEvent事件 gt EventListener事件监听 gt 事件数据Event 这样可以跨sce
  • Charles设置代理后,手机无法上网

    要抓手机app的包 手机配置好代理后 能连接到Charles 但是手机无法上网 原因 Charles开启了White list 解决方式 关闭White List Tools gt White List 实现charles抓取手机访问 ht
  • 解决“您一次只能安装一种 Adobe 产品”问题

    由于dreamweaver不慎升级导致不能用 故准备卸载了重新安装 可是卸载之后一直装不上 总是提示 您一次只能安装一种 Adobe 产品 用优化大师等软件卸载清除注册表信息都不行 搜索后发现一款很好的软件 Windows Installe
  • Python变量类型的强制转换

    当我们需要对数据的类型转换时 只需要将数据类型作为函数名即可 下面给出的函数可以执行数据类型之间的转换 函数返回一个新的对象 表示转换的值 函数格式 使用示例 描述 int x base int 8 可以转换的包括String类型和其他数字
  • 《C++API设计》阅读笔记1

    1 API简介 API Application Programing Interface 提供了对某个问题的抽象 以及客户与解决改问题的软件组件之间进行交互的方式 组件本身通常以软件类库形式分发 它们可以在多个应用程序中使用 概括说 API