C++ API功能設(shè)計的實(shí)現(xiàn)
前言
創(chuàng)建類來表示API中的每個關(guān)鍵對象,同時提供這些類的方法
此處的API風(fēng)格指的是如何表現(xiàn)API的功能,以下4種:
- 純
C API
可以用C編譯器編譯的API。這種API只包含一組自由函數(shù)以及輔助的數(shù)據(jù)結(jié)構(gòu)和常量。這種風(fēng)格的接口不包含對象或繼承,因此被稱為純C模式
- 面向?qū)ο蟮?code>C++ API
這種風(fēng)格涉及對象(其中包含相關(guān)的數(shù)據(jù)與方法)的使用以及繼承、封裝和多態(tài)等概念的應(yīng)用
- 基于模板的
API
通過模板功能,C++也支持泛型編程和元編程。它支持以泛型類型的方式編寫函數(shù)和數(shù)據(jù)結(jié)構(gòu),在以后使用時,泛型類型可以通過具體類型來實(shí)例化,從而實(shí)現(xiàn)特化
- 數(shù)據(jù)驅(qū)動型
API
這類接口的特點(diǎn)是,將參數(shù)通過靈活的數(shù)據(jù)結(jié)構(gòu)打包,連同命名的命令一起發(fā)送給處理程序,而不是調(diào)用特定的方法和自由函數(shù)
純C API
C語言不支持對象封裝和繼承層次結(jié)構(gòu)等概念,因此,純C語法的API必須使用一組更為受限的語言特性來表示,比如typedef、結(jié)構(gòu)體和全局命名空間中的函數(shù)調(diào)用等。因?yàn)?code>C語言中沒有namespace關(guān)鍵字,要避免與其他C庫中的名字發(fā)生沖突,對這種風(fēng)格的API而言,所有公開的函數(shù)和數(shù)據(jù)結(jié)構(gòu)應(yīng)該使用一個公共的前綴
當(dāng)然,也可以使用內(nèi)部鏈接隱藏實(shí)現(xiàn)中的符號名,比如將符號名聲明為靜態(tài)的,這樣它們的作用域就限制在.c文件之中了。通過這種方式,可以確保任何這樣的函數(shù)都不會被導(dǎo)出到外部,從而不會導(dǎo)致符號沖突
// 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);
// 進(jìn)一步改進(jìn)
typedef struct Stack *StackPtr;
void StackPush(StackPtr stack, int val);
int StackPop(StackPtr stack);
bool StackIsEmpty(const StackPtr stack);
// 可以通過特定的API調(diào)用來完成數(shù)據(jù)庫結(jié)構(gòu)的創(chuàng)建與銷毀
StackPtr StackCreate();
void StackDestory(StackPtr stack);在C API的頭文件中使用extern "C"限制,以便C++程序能夠正確的編譯和鏈接C API
#ifdef _cplusplus
extern "C" {
#endif
// C API聲明
#ifdef _cplusplus
}
#endif面向?qū)ο蟮腃++ API
過程式編程、泛型編程、函數(shù)式編程
使用面向?qū)ο蟮?code>C++概念創(chuàng)建二進(jìn)制兼容的API是極為困難的
基于模板的API
模板可以用來編寫在編譯時生成代碼或執(zhí)行代碼的程序(該技術(shù)稱為元編程)
模板可以在編譯時執(zhí)行一些工作,進(jìn)而改進(jìn)運(yùn)行時性能
#include <vector>
template <typename T>
class Stack
{
public:
void Push(T val);
T Pop();
bool IsEmpty() const;
private:
std::vector<T> mStack;
};
// 可以定義一個typedef,這樣就可以更方便地使用該模板實(shí)例了
typedef Stack<int> IntStack;
IntStack *stack = new IntStack();模板實(shí)現(xiàn)方式的另一個選擇是,利用C預(yù)處理器來定義一段文本,可以將其放入多個頭文件中
#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);模板提供了一種類型安全的在編譯時生成代碼的方式。你可以調(diào)試到類模板的時機(jī)代碼行中。除非你要編寫純C API,無法使用模板,否則就應(yīng)該避免使用預(yù)處理器來模擬模板
模板的一個重要屬性是,不同于使用繼承時的動態(tài)(運(yùn)行時)多態(tài),它支持靜態(tài)(編譯時)多態(tài)
不會像虛方法那樣存在運(yùn)行時代價
模板進(jìn)一步的益處,對于特定類型的實(shí)例類,可以特化它的某些方法
template <>
void Stack<int>::Push(int val)
{
// 實(shí)現(xiàn)特定于int類型的壓棧功能
}基于模板的API的缺點(diǎn)
- 最嚴(yán)重的問題是:類模板的定義通常必須出現(xiàn)在公開的頭文件中
- 因?yàn)橐鼗0?,編譯器必須能夠訪問模板代碼的完整定義,顯而易見,這會暴露內(nèi)部細(xì)節(jié)
- 每當(dāng)其他文件包含了類模板定義所在的頭文件時,內(nèi)聯(lián)的代碼都需要重新編譯,生成的代碼會被添加到每個使用該
API的模塊的目標(biāo)文件。這會增加編譯時間,并致使代碼膨脹 - 實(shí)際上有些情況下你可以使用顯式實(shí)例化技術(shù)將模板的實(shí)現(xiàn)隱藏在
.cpp文件中 - 模板的另一個缺點(diǎn)是,模板代碼中出現(xiàn)錯誤時,大多數(shù)編譯器生成的報錯信息都是冗長且令人困惑的,可用
STLFilt
相對于運(yùn)行時開銷而言,代碼體積是需要優(yōu)先考慮的因素,那么應(yīng)該選擇面向?qū)ο蠓桨?,而非模板。或者相反,如果運(yùn)行時性能更為重要,那就應(yīng)該選擇模板
數(shù)據(jù)驅(qū)動型API
數(shù)據(jù)驅(qū)動型程序指的是:通過每次運(yùn)行時提供不同的輸入數(shù)據(jù),它可以執(zhí)行不同的操作
優(yōu)點(diǎn)
- 對于
API將來可能發(fā)生的變化,它的容錯性更強(qiáng) - 可以更容易地支持?jǐn)?shù)據(jù)驅(qū)動型測試技術(shù)
p143
API支持可變參數(shù)列表
- 聯(lián)合體
- 繼承
- void *
到此這篇關(guān)于C++ API功能設(shè)計的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言全面細(xì)致講解單雙精度float與double的使用方法
C語言中小數(shù)的數(shù)據(jù)類型為 float 或 double:float 稱為單精度浮點(diǎn)數(shù),double 稱為雙精度浮點(diǎn)數(shù)。不像整數(shù),小數(shù)的長度始終是固定的,float 占用4個字節(jié),double 占用8個字節(jié)2022-05-05
C++面試題之進(jìn)制轉(zhuǎn)換的實(shí)例
這篇文章主要介紹了C++面試題之進(jìn)制轉(zhuǎn)換的實(shí)例的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這樣的知識,需要的朋友可以參考下2017-10-10
C/C++ 實(shí)現(xiàn)簡易HTTP服務(wù)器的示例
這篇文章主要介紹了C/C++ 實(shí)現(xiàn)簡易HTTP服務(wù)器的示例,幫助大家更好的理解和學(xué)習(xí)C/C++編程,感興趣的朋友可以了解下2020-10-10

