• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      基于C++的反射框架研究與實現(xiàn)

      2021-11-05 08:04:04楊樹仁張啟明孫為康王鴻顯
      電子技術(shù)與軟件工程 2021年17期
      關(guān)鍵詞:基類枚舉對象

      楊樹仁 張啟明 孫為康 王鴻顯

      (中船航海科技有限責(zé)任公司 北京市 100071)

      1 引言

      目前,Java、C#等編程語言具有較為成熟的反射框架,在實踐中受到了廣泛應(yīng)用。但是,C++語言本身并不支持這一動態(tài)特性。雖然,在C++新標(biāo)準(zhǔn)中增加了許多類型信息提取方式,增強了模板元編程能力,但是整體上還不是一套完整的反射框架。目前已有許多不同實現(xiàn)機(jī)理的C++反射框架,如QT、UE4 等,但是與高級語言相比仍存在較大的差距,具有一定的局限性。

      因此,本文主要研究目的是基于C++語言建立一個結(jié)構(gòu)簡單、功能完備、性能高效的通用型反射框架,盡量涵蓋高級編程語言的所有反射功能,為C++反射框架的標(biāo)準(zhǔn)化建設(shè)提供理論指導(dǎo)。

      2 概述

      元數(shù)據(jù)是描述數(shù)據(jù)的數(shù)據(jù),類型元數(shù)據(jù)用于描述類型定義信息[2]。本文中將類型定義信息稱為類型特征信息,將加工處理后的類型特征信息稱為類型元數(shù)據(jù)。反射框架的主要任務(wù)是提取類型特征信息,存入元數(shù)據(jù)倉庫,再通過對元數(shù)據(jù)的合理使用實現(xiàn)反射功能。

      本文設(shè)計的反射框架主要包括特征信息提取、類型注冊、元數(shù)據(jù)應(yīng)用、對象系統(tǒng)四部分。特征信息提取和類型注冊是反射框架的基礎(chǔ),元數(shù)據(jù)應(yīng)用和對象系統(tǒng)是反射框架的成果,只有提取到更加豐富的類型特征,才能建立功能完備的反射框架。

      3 特征信息提取

      特征信息包括基礎(chǔ)信息、函數(shù)信息、屬性信息、注解信息、枚舉信息、基類信息等,以模板元編程作為主要提取手段,在程序編譯階段提取特征信息,提高運行期效率。

      3.1 基礎(chǔ)信息

      基礎(chǔ)信息主要描述類型自身固有信息,如名稱、內(nèi)存大小、類別(枚舉、指針、函數(shù)、容器)、特征(指針特征、裝箱特征、元素特征)等。下面對幾種信息進(jìn)行重點介紹:

      3.1.1 類型名稱

      本文基于內(nèi)置宏(__FUNCSIG__或__PRETTY_FUNCTION__)提取類型名稱,利用模板函數(shù)特化方式返回包含類型名稱的字符串,然后在類型注冊階段加工提取,得到標(biāo)準(zhǔn)化類型名稱。

      3.1.2 指針特征

      指針特征包括指針間址級數(shù)與一級指針信息。一級指針類型是間址級數(shù)為1 的指針類型,可以在無完整類型定義的情況下獲取類型信息,適合作為多級指針的銜接點。

      3.1.3 裝箱特征

      裝箱是對象通用化的一種手段,是將對象存入通用對象(俗稱:箱子)的過程。裝箱特征,也稱為裝箱模式,用于描述對象在箱子內(nèi)部的存儲模式,分為值模式和共享模式。一般值模式對象存儲于棧區(qū),拷貝過程按值傳遞。共享模式對象存儲于堆區(qū),拷貝過程按引入傳遞。

      3.1.4 容器類型

      容器類型主要指STL 容器類型或滿足容器判據(jù)的類型,如vector、list、map、QList 等。容器判據(jù)是判斷類內(nèi)是否定義const_iterator 與value_type 類型或別名。

      3.1.5 元素特征

      主要包括容器元素和模板元素兩種特征。容器元素指容器內(nèi)部存儲類型,如map的元素類型為pair。模板元素類型,指模板參數(shù)類型,如pair的元素類型為T1 和T2。

      元素特征信息提取主要采用分支模板的方式,針對不同類型獲取相應(yīng)的元素類型信息,也可以通過模板特化或偏特化的方式創(chuàng)建自定義的分支模板。

      3.2 函數(shù)信息

      類成員函數(shù)包括普通函數(shù)、靜態(tài)函數(shù)和特殊函數(shù)(默認(rèn)構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、拷貝賦值函數(shù)、析構(gòu)函數(shù)、垃圾回收函數(shù)、運算符重載函數(shù)、元數(shù)據(jù)取值函數(shù)、字符串序列化函數(shù)、哈希碼取值函數(shù)、容器讀寫函數(shù)等)。

      工廠模板的無參特化類型可自動區(qū)分不同函數(shù)類型,簡化函數(shù)代理創(chuàng)建過程。工廠模板的有參偏特化類型可自動區(qū)分同名重載函數(shù)。最終,函數(shù)信息存儲于函數(shù)代理中,以抽象類FunctionProxy作為顯示調(diào)用接口。

      特殊函數(shù)信息提取過程主要依靠編譯器SFINAE 特性自動判定是否存在指定函數(shù),然后利用代理函數(shù)提取函數(shù)信息。下面對幾種特殊函數(shù)進(jìn)行介紹:

      3.2.1 構(gòu)造函數(shù)

      對象構(gòu)造工廠模板是實現(xiàn)對象通用構(gòu)造一種方法,通過引入代理函數(shù)解決了無法獲取構(gòu)造函數(shù)指針的問題,可以適用于任何類型對象的構(gòu)造過程。在應(yīng)用對象構(gòu)造工廠前,先利用SFINAE 特性進(jìn)行條件判定,僅條件成立才注冊構(gòu)造函數(shù)信息。對于平凡類型來說,由于構(gòu)造規(guī)則比較簡單,不必引入代理函數(shù)輔助。

      3.2.2 垃圾回收函數(shù)

      主要服務(wù)于內(nèi)存管理的垃圾回收過程(GC)。當(dāng)GC 過程判定對象不可達(dá)時,會自動執(zhí)行對象的垃圾回收函數(shù),提前通知對象,便于開發(fā)者主動釋放相關(guān)資源。利用SFINAE 特性,當(dāng)且僅當(dāng)類存在垃圾回收函數(shù)時,才提取回收函數(shù)信息,模板判據(jù)是decltype(std::declval().Dispose())。

      3.2.3 元數(shù)據(jù)取值函數(shù)

      是類的虛函數(shù)成員,主要利用虛函數(shù)動態(tài)聯(lián)編特性,運行階段會動態(tài)選擇合適的取值函數(shù)返回正確的類型元數(shù)據(jù)和實際的對象指針,有效地實現(xiàn)接口(或指針)轉(zhuǎn)換。

      3.3 屬性信息

      屬性是面向?qū)ο缶幊痰闹匾拍睿糜诒硎緦ο蟮男再|(zhì)和關(guān)系。在編程語言中,屬性通常具有三個要素:屬性名、get 訪問器、set訪問器。成員變量是自帶屬性名和讀寫訪問器的特殊屬性。

      3.3.1 成員變量信息

      成員變量特征信息主要包括變量名、類型、偏移地址、靜態(tài)特征。其中,變量名通過宏定義參數(shù)字符化方式獲取,變量類型通過decltype 進(jìn)行反向推導(dǎo)獲取,靜態(tài)特征通過模板is_member_object_pointer 進(jìn)行判定,偏移地址通過表達(dá)式addressof(((T*)0)->name)獲取。

      3.3.2 屬性信息提取

      主要包括屬性名、類型、set 訪問器、get 訪問器。通過宏定義的方式主動設(shè)定屬性名與屬性類型。set 訪問器和get 訪問器的獲取方式與類成員函數(shù)信息獲取方式相同。附加了靜態(tài)檢查功能,當(dāng)訪問器類型與屬性類型不一致時,提示編譯錯誤信息。

      3.4 注解信息

      注解是一種支持反射的信息標(biāo)注,是一種更高級的代碼注釋,是對類型、屬性、函數(shù)、枚舉值等定義信息的補充說明。本文的注解與Java 注解概念一致,也等同于C#的特性。

      從編程實現(xiàn)角度出發(fā),注解信息是一種特殊對象,也包括對象類型和對象地址信息,將注解信息附加到指定類型的元數(shù)據(jù)內(nèi),就成為了這個類型特有信息,也稱為類型特性。

      3.5 枚舉信息

      枚舉信息主要用于枚舉值和枚舉名的動態(tài)轉(zhuǎn)換功能。QT 框架提供了Q_ENUMS 簡化了枚舉信息的提取過程,但是僅適用于具有Q_OBJECT 或Q_GADGET 聲明的類內(nèi)枚舉類型,適用范圍有限。

      本文利用可變宏定義的方式,設(shè)計了一種更加簡單有效的枚舉信息提取方法,彌補了QT 無法提取類外枚舉信息的不足。部分宏定義如下:

      其中,DECL_ENUM 用于類內(nèi)枚舉類型的定義,DECL_ENUM_NS 用于類外枚舉類型的定義。將InitHelper 與ValueHelper結(jié)合實現(xiàn)了自動提取枚舉值列表功能,前者判定枚舉值是否存在等號賦值,后者實現(xiàn)枚舉值遞增判定,利用函數(shù)ParseEnumTable 建立枚舉值與枚舉名的映射關(guān)系。

      3.6 基類信息

      基類信息用于描述類的繼承關(guān)系,包括基類類型與地址偏移。由于基類類型無法通過類型推導(dǎo)、內(nèi)置宏、模板元編程等方式自動提取,因此本文主要用宏定義方式實現(xiàn)基類注冊,包括侵入式和非侵入式兩種注冊方式。地址偏移是子類與基類對象間的內(nèi)存地址偏移,主要用于接口變換,可以通過表達(dá)式(int)(intptr_t)(static_cast((T*)1))-1 進(jìn)行計算。

      4 類型注冊

      類型注冊是以元數(shù)據(jù)模型為基礎(chǔ),將特征信息加工處理生成元數(shù)據(jù),再存入元數(shù)據(jù)倉庫的過程。

      4.1 元數(shù)據(jù)模型

      元數(shù)據(jù)模型不僅是類型注冊的基礎(chǔ),也是整個反射框架的基礎(chǔ)。元數(shù)據(jù)以MetaData 作為基類,存儲注解信息,并派生了類型元數(shù)據(jù)、屬性元數(shù)據(jù)、函數(shù)元數(shù)據(jù)。類型元數(shù)據(jù)用于存儲公用的類型信息,派生了指針類型元數(shù)據(jù)、類元數(shù)據(jù)、枚舉類型元數(shù)據(jù)、函數(shù)類型元數(shù)據(jù),分別存儲各自的特征信息。注意區(qū)分函數(shù)類型元數(shù)據(jù)與函數(shù)元數(shù)據(jù),前者主要存儲函數(shù)類型的定義信息,后者主要存儲代理函數(shù)信息。注意區(qū)分類型元數(shù)據(jù)與類元數(shù)據(jù),前者為基類,后者僅存儲class 或struct 類型的特征信息。

      4.2 注冊宏

      類型注冊的核心是MetaRegister,表現(xiàn)形式是注冊宏。注冊宏是簡化類型注冊的有效手段,輔助開發(fā)者快速完成類型反射部分代碼的編寫。

      (1)類型注冊宏:表達(dá)式為REG_TYPE(Type){…},其中類內(nèi)的函數(shù)、屬性、枚舉、注解等信息注冊均在大括號內(nèi)完成。程序執(zhí)行階段的類型注冊過程均會在main 函數(shù)前完成。

      (2)函數(shù)注冊宏:表達(dá)式為REG_FUNCTION(Name)或REG_FUNCTION(Name,Define),后者主要用于注冊重載函數(shù)。

      (3)構(gòu)造注冊宏:用于注冊構(gòu)造函數(shù),表達(dá)式為REG_CTOR(ArgTypes),其中ArgTypes 表示形參類型。

      (4)屬性注冊宏:表達(dá)式為 REG_PROPERTY(Name) 或REG_PROPERTY(Name,Type,[[Getter],[Setter]]),前者用于注冊成員變量信息,后者的Getter 和Setter 表示可選的訪問器函數(shù)名,可按需添加相應(yīng)的訪問器。

      (5)注解注冊宏:基本形式為ANNOTATION(Type(Args),[Fi eld=Value])。如果附加在類型注冊宏后,表示為類型添加注解;附加在函數(shù)注冊宏后,表示為函數(shù)添加注解;附加在屬性注冊宏后,表示為屬性添加注解。

      (6)枚舉注冊宏:表達(dá)式為DECL_ENUM(Type,Values)或DECL_ENUM_NS(Type,Values),前者用于定于類內(nèi)枚舉類型,后者用于定義類外枚舉類型。

      (7)基類注冊宏:表達(dá)式為REG_BASE(Type,Bases)或REG_BASE_NS(Type,Bases),前者屬于侵入式,后者屬于非侵入式,表達(dá)的意思相同。

      4.3 合法性檢查

      合法性檢查是在程序運行期檢查類型信息合法性,與編譯階段靜態(tài)斷言相結(jié)合,能夠有效避免人為錯誤。

      5 元數(shù)據(jù)應(yīng)用

      如圖7所示,元數(shù)據(jù)模型對外提供了四個基礎(chǔ)類型:MetaType、MetaProperty、MetaFunction 和MetaAnnotation,分別應(yīng)用類型信息、屬性信息、函數(shù)信息以及注解信息實現(xiàn)動態(tài)反射功能。其中MetaType 主要實現(xiàn)類型檢索、動態(tài)構(gòu)造、成員檢索、基類檢索、萬能轉(zhuǎn)換等功能;MetaProperty 主要實現(xiàn)屬性動態(tài)讀寫功能;MetaFunction 主要實現(xiàn)函數(shù)動態(tài)調(diào)用功能;MetaAnnotation 主要實現(xiàn)注解信息動態(tài)讀取功能。

      6 對象系統(tǒng)

      對象系統(tǒng)主要提供數(shù)據(jù)通用化封裝方法,表現(xiàn)為對象裝箱和拆箱操作。裝箱是將對象封裝為通用對象的過程。拆箱是將通用對象轉(zhuǎn)換成指定類型對象或接口的過程。反射框架的重要應(yīng)用成果,就是實現(xiàn)對通用對象的構(gòu)建、傳遞、屬性讀寫、函數(shù)調(diào)用等功能。

      共享模式主要基于共享智能指針的思想實現(xiàn)的,通過引用計數(shù)器表示對象的使用情況,在計數(shù)器為0 時自動釋放共享內(nèi)存。然而,這種方式不可避免的會進(jìn)入智能指針的依賴陷阱,即閉環(huán)引用問題。為了解決這個問題,本文引入了垃圾回收機(jī)制,主要基于標(biāo)記清除算法,將不可達(dá)對象執(zhí)行自動回收,可以有效回收閉環(huán)孤島,同時采用分代回收策略提高垃圾回收效率。

      7 結(jié)束語

      本文基于C++語言設(shè)計了一個結(jié)構(gòu)簡單、性能高效、功能完備的通用版反射框架,具有特征信息提取、類型注冊、元數(shù)據(jù)應(yīng)用和對象系統(tǒng)四大主要模塊,設(shè)計了有效的元數(shù)據(jù)模型以及對象系統(tǒng)模型,實現(xiàn)了萬能轉(zhuǎn)換、動態(tài)構(gòu)造、動態(tài)屬性讀寫、動態(tài)函數(shù)調(diào)用、注解反射、裝箱拆箱、垃圾回收等高級功能,幾乎涵蓋了高級語言的所有反射特性。本文設(shè)計的反射框架要求編譯器至少支持C++11標(biāo)準(zhǔn),經(jīng)測試,能夠在GCC4.8.1 下正常編譯運行。

      猜你喜歡
      基類枚舉對象
      神秘來電
      睿士(2023年2期)2023-03-02 02:01:09
      基于理解性教學(xué)的信息技術(shù)教學(xué)案例研究
      速讀·上旬(2022年2期)2022-04-10 16:42:14
      基于C#面向?qū)ο蟪绦蛟O(shè)計的封裝、繼承和多態(tài)分析
      一種高效的概率圖上Top-K極大團(tuán)枚舉算法
      攻略對象的心思好難猜
      意林(2018年3期)2018-03-02 15:17:24
      基于熵的快速掃描法的FNEA初始對象的生成方法
      空戰(zhàn)游戲設(shè)計實例
      基于太陽影子定位枚舉法模型的研究
      區(qū)間對象族的可鎮(zhèn)定性分析
      一種基于用戶興趣的STC改進(jìn)算法
      广南县| 通榆县| 托克托县| 茂名市| 裕民县| 宝坻区| 饶平县| 娄烦县| 盘山县| 古交市| 白河县| 英德市| 井冈山市| 普陀区| 湟源县| 富顺县| 庆云县| 永修县| 石阡县| 集安市| 香港| 军事| 榆社县| 依兰县| 常熟市| 阿尔山市| 潼关县| 寿宁县| 尤溪县| 鱼台县| 阳山县| 曲松县| 东源县| 社旗县| 遂平县| 岳西县| 延吉市| 镇平县| 阿巴嘎旗| 旺苍县| 佳木斯市|