中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

C++接口類工程化方法有哪些

發布時間:2021-11-24 11:02:03 來源:億速云 閱讀:133 作者:iii 欄目:互聯網科技

本篇內容介紹了“C++接口類工程化方法有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

接口分為調用接口與回調接口,調用接口主要實現模塊解耦的作用,只要保持接口兼容性,模塊內部的升級對用戶可以做到無感知。良好的接口分層有助于各業務團隊高效率開發。

回調接口主要用于系統有異步事件需要通知用戶。系統預定義接口形式,并由用戶注冊,具體調用時機由系統決定。

調用接口

假設有一個網絡發送模塊類Network,類定義如下:

class Network{public:bool send();}

虛函數

最常用的就是虛函數,可以使用虛函數定義Network接口類:

class Network{  public:  virtual bool send()=0  static Network* New();  static void Delete(Network* network_);}

將send定義為虛函數,由繼承類去實現(比如由PLC模塊或者以太模塊繼承),以靜態方法創建子類對象,以基類Network的指針返回給業務使用。資源遵循誰創建誰銷毀的原則,基類還提供Delete方法銷毀對象。因為對象銷毀封裝在接口內部,因此Network接口類可以不需要虛析構函數。

代碼使用虛函數易讀性較高,但是虛函數開銷較大(需要使用虛函數表指針間接調用),無法在編譯期間內聯優化,而事實上調用接口在編譯期就能確定使用哪個函數,不需要用到虛函數的動態特性。此外由于虛函數使用虛函數表指針間接調用的原因,增加虛函數會導致函數地址表索引變化,新增接口不能在二進制層面兼容老接口。而且由于用戶可能繼承了Network接口類,在末尾增加虛函數也有風險,因此虛函數接口一旦發布上線就基本無法修改。

指向實現的指針

可以使用指向實現的指針來定義Network接口類:

class NetworkImpl;class Network{  public:  bool send();  static Network* New();  Network()  ~Network();  private:  NetworkImpl* impl;}

Network的具體實現由NetworkImpl完成,通過使用指向實現的指針的方式來定義接口,接口類對象的創建和銷毀可以由用戶負責,更好的管理對象生命周期。

此外該方法通用性強,新增接口不會影響二進制兼容性,有利于項目快速迭代。

但是該方法還是增加了一層調用,對性能還是略微有影響,不符合C++的零開銷原則。

隱藏的子類

隱藏的子類思想很簡單,接口要實現的目標就是解耦,主要就是隱藏實現,也就是隱藏接口類的成員變量。如果能將接口類的成員變量都轉移到另一個隱藏類中,那么接口類就不需要任何成員變量,那么就達到了隱藏實現的目的。具體實現方法如下:

class Network{  public:  bool send();  static Network* New();  static void Delete(Network* network_);  protected:  Network();  ~ Network();}

Network接口類只有成員函數,沒有成員變量。提供靜態方法New創建對象,Delete方法銷毀對象。New方法的實現中會創建隱藏的子類NetworkImol的對象,并以父類Network指針的形式返回。NetworkImol類中定義了Network類的成員變量,并將Network類聲明為friend:

class NetworkImol:public Network{  friend class Network ;  private:  // 定義Network類的成員變量}

Network類的實現中創建NetworkImol子類對象,并以父類指針形式返回,通過將this強制轉換為子類NetworkImol類型的指針來訪問成員變量:

bool Network::send(){  NetworkImpl* impl = (NetworkImpl*)this;  //通過impl訪問成員變量,實現Network的功能}static Network* New(){  return new NetworkImpl();}static Delete(Network* network){  delete (NetworkImpl*)network;}

該方法符合C++零開銷原則,且同樣符合二進制兼容性。

Rust語言中有一種Trait功能,可以在類外面實現一個Trait(不需要修改類代碼),那么C++同樣可以參考實現Trait功能假設需要在Network類中實現發送序列化數據,重新設計Network接口,Serializable類定義如下:

class Serializable{public:  virtual void serialize()const =0;};

Network類定義如下:

class Network{public:  bool send(const char* host, uint16_t port,constSerializable& buf);}

Serializable接口類似于Rust中的Trait,現在任何實現了Serializable接口類的對象都可以通過調用Network類接口完成數據發送功能。那么問題來了,加入項目迭代需要增加通過Network類發送int型數據,如何在不修改類定義的同時實現Serializable接口呢?很簡單:

class IntSerializable  :public Serializable{public:IntSerializable(const int i):intthis(i){}virtual void serialize() const override{  buffer += std::to_string(*intthis);}private:  const int* const intthis;};

之后就可以通過Network發送int型數據了:

Network* network = Network::New();int i=1;network->send(ip,port, IntSerializable(i));

非侵入式接口將類和接口區分開來,類中的數據只包含成員變量,不包含虛函數表指針,因此類不會因為實現了n個接口而引入n個虛函數表指針。而接口中只包含虛函數表指針,不包含數據成員,類和接口之間通過實現類進行類型轉換,類只有在充當接口使用的時候才會引入虛函數表指針,不充當接口的時候不會引入,符合C++零開銷原則。

Rust編譯器通過impl關鍵字記錄了每個類實現了哪些Trait,因此在賦值時編譯器可以自動完成將對象轉換為對應的Trait類型。而g++等C++編譯器并沒有記錄這些轉換信息,因此需要手動轉換類型。本質上還是通過代碼幫編譯器記錄每個接口類實現了哪些Trait,使用模板類的繼承,在編譯期實現類似“靜態多態”的功能。

“C++接口類工程化方法有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

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

c++
AI

玛多县| 门头沟区| 武义县| 盐山县| 务川| 仪陇县| 资兴市| 湛江市| 新田县| 阿鲁科尔沁旗| 阳原县| 昭通市| 抚远县| 尉犁县| 青阳县| 开原市| 兴安县| 宁陕县| 牡丹江市| 错那县| 鄂伦春自治旗| 泸西县| 黄浦区| 古丈县| 汕尾市| 丰顺县| 会同县| 萍乡市| 启东市| 房产| 黔东| 汾西县| 同心县| 赫章县| 枝江市| 巴彦淖尔市| 盘山县| 衡阳县| 平乡县| 新乡市| 北京市|