日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++?API功能設計的實現_C 語言

作者:Colin-YYYY ? 更新時間: 2022-10-25 編程語言

前言

創建類來表示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 *

原文鏈接:https://blog.csdn.net/qq_29935433/article/details/126528731

欄目分類
最近更新