91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

API的設計方法是什么

發布時間:2021-10-25 11:31:22 來源:億速云 閱讀:148 作者:iii 欄目:開發技術

本篇內容主要講解“API的設計方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“API的設計方法是什么”吧!

假設提供TestFun作為一個對外接口,我們編譯并制作為靜態庫:

$ g++ -c api.cc -I./ $ ar -rcs libapi.a api.o

關于靜態庫的制作,請參考《Linux下如何制作靜態庫?》。

另外一個程序main.cc這么使用它:

// 來源:公眾號編程珠璣 // 作者:守望先生 #include "api.h" int main(){     Param param;     param.num = 10;     param.str = "24";      TestFun(param);     return 0; }

編譯鏈接使用:

$ g++ -o main main.cc -L./ -lapi -I ./ $ ./main

看起來并沒有什么問題,有新的參數,可以直接在Param中增加即可,擴展性也不錯。

問題來了

目前來看是沒有什么問題的,但是假設,還有另外一個庫要使用它,例如:

// 來源:公眾號編程珠璣 // 作者:守望先生 // use_api.h #include"api.h" void UseApi();  // use_api.cc #include"use_api.h" void UseApi(){     Param param;     param.num = 10;     param.str = "24";      TestFun(param); }

也將它作為靜態庫:

$ g++ -c use_api.cc -I./ $ ar -rcs libuse_api.a use_api.o

這個時候同樣主程序會用到我們的原始api,但是卻使用了不同的版本,比如,新增了Param中新增了一個字段ext:

// 來源:公眾號【編程珠璣】 // 作者:守望先生 // api.h #include<iostream> struct Param{     int num;     std::string str;     std::string ext; }; void TestFun(const Param &param);  // api.cc #include "api.h" void TestFun(const Param &param){     std::cout<<"num:"<<param.num<<" str:"<<param.str.c_str()<<" ext:"<<param.ext.c_str()<<std::endl; }

重新生成靜態庫:

$ g++ -c api.cc -I./ $ ar -rcs libapi.a api.o

這個時候,通過use_api使用api接口,但是鏈接新的庫:

// 來源:公眾號編程珠璣 // 作者:守望先生 #include "use_api.h" int main(){     UseApi();     return 0; }

這個時候,再去編譯鏈接,并運行:

$ g++ -o main main.cc -I./ -L./ -luse_api -lapi $ ./main Segmentation fault (core dumped)

看到沒有,喜聞樂見的core dumped了,分析core還會發現,是由于訪問非法地址導致的。

我們再來梳理一下這個過程:

  • 提供庫libapi.a版本A

  • libuse_api使用版本A進行編譯,使用A版本的頭文件

  • libapi.a庫升級到B版本,其中頭文件中增加了字段,并且實現也引用了新的字段

  • 主程序使用了use_api,但是鏈接了版本B的libapi.a庫

這個時候,版本B的實現訪問了新的字段,還是use_api中還是使用A版本,并沒有傳入新字段,因此自然會導致非法訪問。

如何解決?

很簡單,不直接暴露成員,而是提供setter和getter,而提供方式和前面提到的PIMPL方法類似。

// api.h // 來源:公眾號編程珠璣 // 作者:守望先生 #include<iostream> #include<memory> class Param{ public:     void SetNum(int num);     int GetNum() const;     void SetStr(const std::string &str);     std::string GetStr() const;     void SetExt(const std::string &str);     std::string GetExt() const;     Param();   private:     class ParamImpl;     std::unique_ptr<ParamImpl> param_impl_; }; void TestFun(const Param &param);

在這里頭文件中只提供setter和getter,而完全不暴露成員,具體成員的設置在ParamImpl中實現:

// api.cc // 來源:公眾號編程珠璣 // 作者:守望先生 #include "api.h" class Param::ParamImpl{   public:     int num;     std::string str;     std::string ext; }; Param::Param(){     param_impl_.reset(new ParamImpl); } // 析構函數必須要 Param::~Param() = default; void Param::SetNum(int num){     param_impl_->num = num; } int Param::GetNum() const {     return  param_impl_->num; } void Param::SetStr(const std::string &str){     param_impl_->str = str; } void Param::SetExt(const std::string &ext){     param_impl_->ext = ext; } std::string Param::GetStr() const {     return param_impl_->str; } std::string Param::GetExt() const {     return param_impl_->ext; } void TestFun(const Param &param){     std::cout<<"num:"<<param.GetNum()<<" str:"<<param.GetStr().c_str()<<"ext:"<<param.GetExt().c_str()<<std::endl; }

通過上面的方式,不會直接暴露成員函數,而是提供接口設置或者獲取,而在實現中,即便出現新的版本增加了接口,最多也只是獲取到默認值,而不會導致程序崩潰。

到此,相信大家對“API的設計方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

api
AI

永嘉县| 绥宁县| 登封市| 临潭县| 肇源县| 通河县| 灵丘县| 和硕县| 永寿县| 石门县| 玉山县| 响水县| 山东| 屏山县| 淳安县| 山西省| 博白县| 高青县| 务川| 金湖县| 邵阳县| 乐山市| 长春市| 吉安县| 西平县| 宜君县| 荣昌县| 石屏县| 华坪县| 九龙坡区| 顺义区| 杭锦后旗| 建瓯市| 长岭县| 彭州市| 罗山县| 浙江省| 武强县| 乐昌市| 鸡西市| 尉犁县|