日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 宏、范型和RTTI 浅析

發布時間:2023/12/10 c/c++ 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 宏、范型和RTTI 浅析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【摘要】
? ? ? ?RTTI(Run-Time?Type?Identification)是面向對象程序設計中一種重要的技術。

現行的C++標準對RTTI已經有了明白的支持。

只是在某些情況下出于特殊的開發須要,我們須要自己編碼來實現。本文介紹了一些關于RTTI的基礎知識及其原理和實現,并分析比較三者是線上的差異與聯系。


【正文】

RTTI 的需求

? ? ? ?和非常多其它語言一樣,C++是一種靜態類型語言。其數據類型是在編譯期就確定的,不能在執行時更改。然而因為面向對象程序設計中多態性的要求,C++中的指針或引用(Reference)本身的類型,可能與它實際代表(指向或引用)的類型并不一致。

有時我們須要將一個多態指針轉換為事實上際指向對象的類型。就須要知道執行時的類型信息。這就產生了執行時類型識別的要求。


C++對RTTI的支持

? ? ?C++提供了兩個keywordtypeid和dynamic_cast,一個type_info來支持RTTI。

? ?? dynamic_cast操作符:它同意在執行時刻進行類型轉換,從而使程序可以在一個類層次結構安全地轉換類型。dynamic_cast提供了兩種轉換方式。把基類指針轉換成派生類指針,或者把指向基類的左值轉換成派生類的引用。

見下例講述:

void company::payroll(employee *pe) { //對指針轉換失敗,dynamic_cast返回NULL if(programmer *pm=dynamic_cast(pe)){ pm->bonus(); } }void company::payroll(employee &re) { try{ //對引用轉換失敗的話,則會以拋出異常來報告錯誤 programmer &rm=dynamic_cast(re); pm->bonus(); } catch(std::bad_cast){ } }? ? ? ? ?這里bonus是programmer的成員函數,基類employee不具備這個特性。

所以我們必須使用安全的由基類到派生類類型轉換,識別出programmer指針。


? ? ??typeid操作符:它指出指針或引用指向的對象的實際派生類型。


? ? ? ?比如:
employee* pe=new manager; typeid(*pe)==typeid(manager) //true ? ? ? ?typeid能夠用于作用于各種類型名,對象和內置基本數據類型的實例、指針或者引用,當作用于指針和引用將返回它實際指向對象的類型信息。typeid的返回是type_info類型。


? ? ? ?type_info類:這個類的確切定義是與編譯器實現相關的。以下是《C++?Primer》中給出的定義(參考資料[2]中談到編譯器必須提供的最小信息量):
class type_info { private: type_info(const type_info&); type_info& operator=( const type_info& ); public: virtual ~type_info(); int operator==( const type_info& ) const; int operator!=( const type_info& ) const; const char* name() const; };

詳見:http://bbs.csdn.net/topics/40414128


三者比較:

宏能夠在編譯前用字符替換的辦法展開,減輕程序猿反復編碼的工作量。



c++的范型(模版)也是在編譯時確定終于的程序樣式。他用的辦法是編譯時確定類型信息。

RTTI是執行期類型信息,能夠在執行時得到對象的類型信息。

我們考察一個程序,為了說明問題,我特意找了一個簡單的程序,這個程序比較a和b,假設a大于b就交換他們。可是。a、b的類型并不確定可能是字符串也可能是整數還可能是復數。為了簡潔和不至于造成過的混淆,我不使用操作符重載。假定不論什么操作都是基于對象方法的,為了完畢這個函數。a、b必須支持compare(比較)和swape(交換)方法。

我們不清楚a、b的類型,假設有3種類型我們就必須寫3個函數嗎?那太累人了。我們用來定義這個函數好了。
#define?exchange(a,b)?if(a.compare(b))a.swape(b);
這樣我們在使用的時候就能夠直接使用exchange宏來表達這個函數,并且能夠適應各種類型,僅僅要他們都支持這兩個函數就能夠。



我們還能夠用范型來實現這個函數
template<typename?T>
void?exchange(T?&a,?T?&b)
{
??if(a.compare(b))a.swape(b)
}
我們相同達到了目的。

假設編譯器支持豐富的RTTI,我們還能夠用腳本語言的方式來實現他們。
exchange(a,?b)
{
??if(a.compare(b))a.swape(b);
}

上面三種方式區別在哪里呢?
第一種。使用字符替換的方式,在編譯前展開宏,使之成為程序中的一段代碼。


另外一種,在編譯時。確定調用函數的參數的類型,并自己主動生成一個這個類型的暫時函數。
第三種。在執行時依據參數的類型確定是否可以執行這段程序。
前2種都是在編譯時確認的。第三種是在執行時確定的。
在程序設計中有著大量的反復代碼,我們須要一種方法來提高效率,可是為什么看著結構類似的程序須要反復代碼呢?最重要的原因是,傳統的程序中實體(函數、變量、屬性等等)在編譯時都須要內存中一塊確定的地址(或者相對基址的偏移)來指代。這時cpu處理方式的內在要求,而這個和程序設計時依照名字引用的思維習慣是不一致的。
我們能夠用宏和模版來取代手工對每一個類型的特化,可是在程序中仍然是使用地址來指代實體的。實際上每一個類型的特化程序依舊存在,僅僅是在程序設計外觀上不可見了。
第三種方式。使用RTTI。程序中的實體都不再是確定的地址來指代,而是通過字符串名稱(或者實體表)來指代,在執行時依據名稱來特化。這樣的方法和前2個方法是本質的不同。


使用RTTI能夠在非常大程度上減輕宏和靜態模版帶來的副作用,使程序具有更加優雅的外觀。
可是。C++的宏和靜態模版也不是一無是處。他用在對效率更加嚴格場合是很合適的。

轉載于:https://www.cnblogs.com/llguanli/p/8286541.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的C++ 宏、范型和RTTI 浅析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。