C++ API

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

C++ API

Colin-YYYY   2022-09-29 我要评论

前言

创建类来表示API中的每个关键对象,同时提供这些类的方法

此处的API风格指的是如何表现API的功能,以下4种:

  • C API

可以用C编译器编译的API。这种API只包含一组自由函数以及辅助的数据结构和常量。这种风格的接口不包含对象或继承,因此被称为纯C模式

  • 面向对象的C++ API

这种风格涉及对象(其中包含相关的数据与方法)的使用以及继承、封装和多态等概念的应用

  • 基于模板的API

通过模板功能,C++也支持泛型编程和元编程。它支持以泛型类型的方式编写函数和数据结构,在以后使用时,泛型类型可以通过具体类型来实例化,从而实现特化

  • 数据驱动型API

这类接口的特点是,将参数通过灵活的数据结构打包,连同命名的命令一起发送给处理程序,而不是调用特定的方法和自由函数

纯C API

C语言不支持对象封装和继承层次结构等概念,因此,纯C语法的API必须使用一组更为受限的语言特性来表示,比如typedef、结构体和全局命名空间中的函数调用等。因为C语言中没有namespace关键字,要避免与其他C库中的名字发生冲突,对这种风格的API而言,所有公开的函数和数据结构应该使用一个公共的前缀

当然,也可以使用内部链接隐藏实现中的符号名,比如将符号名声明为静态的,这样它们的作用域就限制在.c文件之中了。通过这种方式,可以确保任何这样的函数都不会被导出到外部,从而不会导致符号冲突

// c++ 示例
class Stack
{
public:
    void Push(int val);
    int Pop();
    bool IsEmpty() const;
private:
    int *mStack;
    int mCurSize;
};
// 纯C API
struct Stack
{
    int *mStack;
    int mCurSize;
};
void StackPush(struct Stack *stack, int val);
int StackPop(struct Stack *stack);
bool StackIsEmpty(const struct Stack *stack);
// 进一步改进
typedef struct Stack *StackPtr;
void StackPush(StackPtr stack, int val);
int StackPop(StackPtr stack);
bool StackIsEmpty(const StackPtr stack);
// 可以通过特定的API调用来完成数据库结构的创建与销毁
StackPtr StackCreate();
void StackDestory(StackPtr stack);

C API的头文件中使用extern "C"限制,以便C++程序能够正确的编译和链接C API

#ifdef _cplusplus
extern "C" {
#endif
// C API声明
#ifdef _cplusplus
}
#endif

面向对象的C++ API

过程式编程、泛型编程、函数式编程

使用面向对象的C++概念创建二进制兼容的API是极为困难的

基于模板的API

模板可以用来编写在编译时生成代码或执行代码的程序(该技术称为元编程)

模板可以在编译时执行一些工作,进而改进运行时性能

#include <vector>
template <typename T>
class Stack
{
public:
    void Push(T val);
    T Pop();
    bool IsEmpty() const;
private:
    std::vector<T> mStack;
};
// 可以定义一个typedef,这样就可以更方便地使用该模板实例了
typedef Stack<int> IntStack;
IntStack *stack = new IntStack();

模板实现方式的另一个选择是,利用C预处理器来定义一段文本,可以将其放入多个头文件中

#include <vector>
#define DECLARE_STACK(Prefix, T) \
class Prefix##Stack \
{ \
public: \
    void Push(T val); \
    T Pop(); \
    bool IsEmpty() const; \
    
private: \
    std::vector<T> mStack; \
}
DECLARE_STACK(Int, int);

模板提供了一种类型安全的在编译时生成代码的方式。你可以调试到类模板的时机代码行中。除非你要编写纯C API,无法使用模板,否则就应该避免使用预处理器来模拟模板

模板的一个重要属性是,不同于使用继承时的动态(运行时)多态,它支持静态(编译时)多态

不会像虚方法那样存在运行时代价

模板进一步的益处,对于特定类型的实例类,可以特化它的某些方法

template <>
void Stack<int>::Push(int val)
{
    // 实现特定于int类型的压栈功能
}

基于模板的API的缺点

  • 最严重的问题是:类模板的定义通常必须出现在公开的头文件中
  • 因为要特化模板,编译器必须能够访问模板代码的完整定义,显而易见,这会暴露内部细节
  • 每当其他文件包含了类模板定义所在的头文件时,内联的代码都需要重新编译,生成的代码会被添加到每个使用该API的模块的目标文件。这会增加编译时间,并致使代码膨胀
  • 实际上有些情况下你可以使用显式实例化技术将模板的实现隐藏在.cpp文件中
  • 模板的另一个缺点是,模板代码中出现错误时,大多数编译器生成的报错信息都是冗长且令人困惑的,可用STLFilt

相对于运行时开销而言,代码体积是需要优先考虑的因素,那么应该选择面向对象方案,而非模板。或者相反,如果运行时性能更为重要,那就应该选择模板

数据驱动型API

数据驱动型程序指的是:通过每次运行时提供不同的输入数据,它可以执行不同的操作

优点

  • 对于API将来可能发生的变化,它的容错性更强
  • 可以更容易地支持数据驱动型测试技术p143

API支持可变参数列表

  • 联合体
  • 继承
  • void *

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们