青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
數據加載中……

如何在運行時確定對象類型(RTTI) 轉

RTTI 是“Runtime Type Information”的縮寫,意思是:運行時類型信息。它提供了運行時確定對象類型的方法。本文將簡略介紹 RTTI 的一些背景知識、描述 RTTI 的概念,并通過具體例子和代碼介紹什么時候使用以及如何使用 RTTI;本文還將詳細描述兩個重要的 RTTI 運算符的使用方法,它們是 typeid 和 dynamic_cast。
    其實,RTTI 在C++中并不是什么新的東西,它早在十多年以前就已經出現了。但是大多數開發人員,包括許多高層次的C++程序員對它并不怎么熟悉,更不用說使用 RTTI 來設計和編寫應用程序了。
    一些面向對象專家在傳播自己的設計理念時,大多都主張在設計和開發中明智地使用虛擬成員函數,而不用 RTTI 機制。但是,在很多情況下,虛擬函數無法克服本身的局限。每每涉及到處理異類容器和根基類層次(如 MFC)時,不可避免要對對象類型進行動態判斷,也就是動態類型的偵測。如何確定對象的動態類型呢?答案是使用內建的 RTTI 中的運算符:typeid 和 dynamic_cast。
    首先讓我們來設計一個類層次,假設我們創建了某個處理文件的抽象基類。它聲明下列純虛擬函數:open()、close()、read()和 write():
class File
{
public:
virtual int open(const string & filename)=0;
virtual int close(const string & filename)=0;
//
virtual ~File()=0; // 記住添加純虛擬析構函數(dtor)
};
現在從 File 類派生的類要實現基類的純虛擬函數,同時還要提供一些其他的操作。假設派生類為 DiskFile,除了實現基類的純虛擬函數外,還要實現自己的flush()和defragment()操作:
class DiskFile: public File
{
public:
int open(const string & filename);

// 實現其他的純虛擬函數
......

// 自己的專有操作
virtual int flush();
virtual int defragment();
};
接著,又從 DiskFile 類派生兩個類,假設為 TextFile 和 MediaFile。前者針對文本文件,后者針對音頻和視頻文件:
class TextFile: public DiskFile
{
// ......
int sort_by_words();
};

class MediaFile: public DiskFile
{
//......
};
我們之所以要創建這樣的類層次,是因為這樣做以后可以創建多態對象,如:
File *pfile; // *pfile的靜態類型是 File
if(some_condition)
pfile = new TextFile; // 動態類型是 TextFile
else
pfile = new DiskFile; // 動態類型是 DiskFile
    假設你正在開發一個基于圖形用戶界面(GUI)的文件管理器,每個文件都可以以圖標方式顯示。當鼠標移到圖標上并單擊右鍵時,文件管理器打開一個菜單,每 個文件除了共同的菜單項,不同的文件類型還有不同的菜單項。如:共同的菜單項有“打開”“拷貝”、和“粘貼”,此外,還有一些針對特殊文件的專門操作。比 如,文本文件會有“編輯”操作,而多媒體文件則會有“播放”菜單。為了使用 RTTI 來動態定制菜單,文件管理器必須偵測每個文件的動態類型。利用 運算符 typeid 可以獲取與某個對象關聯的運行時類型信息。typeid 有一個參數,傳遞對象或類型名。因此,為了確定 x 的動態類型是不是Y,可以用表達式:typeid(x) == typeid(Y)實現:
#include <typeinfo> // typeid 需要的頭文件
void menu::build(const File * pfile)
{
if (typeid(*pfile)==typeid(TextFile))
{
add_option("edit");
}
else if (typeid(*pfile)==typeid(MediaFile))
{
add_option("play");
}
}
    使用 typeid 要注意一個問題,那就是某些編譯器(如 Visual C++)默認狀態是禁用 RTTI 的,目的是消除性能上的開銷。如果你的程序確實使用了 RTTI,一定要記住在編譯前啟用 RTTI。使用 typeid 可能產生一些將來的維護問題。假設你決定擴展上述的類層次,從MediaFile 派生另一個叫 LocalizeMedia 的類,用這個類表示帶有不同語言說明文字的媒體文件。但 LocalizeMedia 本質上還是個 MediaFile 類型的文件。因此,當用戶在該類文件圖標上單擊右鍵時,文件管理器必須提供一個“播放”菜單。可惜 build()成員函數會調用失敗,原因是你沒有檢查這種特定的文件類型。為了解決這個問題,你必須象下面這樣對 build() 打補?。?
void menu::build(const File * pfile)
{

//......

else if (typeid(*pfile)==typeid(LocalizedMedia))
{
add_option("play");
}
}
    唉,這種做法真是顯得太業余了,以后每次添加新的類,毫無疑問都必須打類似的補丁。顯然,這不是一個理想的解決方案。這個時候我們就要用到 dynamic_cast,這個運算符用于多態編程中保證在運行時發生正確的轉換(即編譯器無法驗證是否發生正確的轉換)。用它來確定某個對象是 MediaFile 對象還是它的派生類對象。dynamic_cast 常用于從多態編程基類指針向派生類指針的向下類型轉換。它有兩個參數:一個是類型名;另一個是多態對象的指針或引用。其功能是在運行時將對象強制轉換為目標類型并返回布爾型結果。也就是說,如果該函數成功地并且是動態的將 *pfile 強制轉換為 MediaFile,那么 pfile的動態類型是 MediaFile 或者是它的派生類。否則,pfile 則為其它的類型:
void menu::build(const File * pfile)
{
if (dynamic_cast <MediaFile *> (pfile))
{
// pfile 是 MediaFile 或者是MediaFile的派生類 LocalizedMedia
add_option("play");
}
else if (dynamic_cast <TextFile*> (pfile))
{
// pfile 是 TextFile 是TextFile的派生類
add_option("edit");
}
}
    細細想一下,雖然使用 dynamic_cast 確實很好地解決了我們的問題,但也需要我們付出代價,那就是與 typeid 相比,dynamic_cast 不是一個常量時間的操作。為了確定是否能完成強制類型轉換,dynamic_cast`必須在運行時進行一些轉換細節操作。因此在使用 dynamic_cast 操作時,應該權衡對性能的影響。

posted on 2008-11-19 14:59 井泉 閱讀(980) 評論(1)  編輯 收藏 引用 所屬分類: C++

評論

# re: 如何在運行時確定對象類型(RTTI) 轉  回復  更多評論   

很好,學習了
2012-03-28 15:55 | kelvn
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美激情成人在线视频| 国产日韩专区在线| 99re亚洲国产精品| 亚洲国产精品黑人久久久| 香蕉成人伊视频在线观看| 亚洲私人影吧| 亚洲一区二区三区欧美| 亚洲一二三区视频在线观看| 亚洲欧美国产日韩天堂区| 午夜日韩在线观看| 久久久国产精品亚洲一区 | 99国产精品99久久久久久粉嫩| 亚洲日本欧美在线| 亚洲午夜精品一区二区| 欧美中文字幕第一页| 女人色偷偷aa久久天堂| 亚洲伦理在线观看| 香蕉成人伊视频在线观看| 久久久久免费观看| 欧美日本久久| 国产在线精品一区二区夜色| 亚洲国产乱码最新视频| 午夜久久一区| 亚洲激情av| 久久成人资源| 欧美日韩在线另类| 1024亚洲| 小黄鸭精品aⅴ导航网站入口| 狂野欧美激情性xxxx欧美| 日韩视频中文| 欧美 日韩 国产在线| 国产精品一卡| 亚洲乱码日产精品bd| 久久久久欧美精品| 亚洲图片你懂的| 欧美freesex8一10精品| 国产一区二区高清不卡| 亚洲一区二区三区精品视频| 欧美高清一区二区| 午夜精品久久久久久久99樱桃| 国产欧美va欧美va香蕉在| 欧美日韩一区二区三区在线| 在线观看欧美| 欧美在线3区| 日韩亚洲欧美综合| 狼人社综合社区| 国产色综合久久| 午夜精品久久久99热福利| 亚洲激情国产精品| 美国十次成人| 亚洲国产精品久久久久婷婷884| 午夜精品福利一区二区蜜股av| 亚洲精选视频免费看| 免费在线播放第一区高清av| 狠狠久久婷婷| 久久一区二区三区四区| 欧美一级在线播放| 国产三区精品| 久久婷婷人人澡人人喊人人爽| 亚洲欧美日本国产有色| 国产精品久久久久毛片软件| 一区二区三区国产在线| 亚洲激情网站免费观看| 欧美激情精品久久久久久变态| 亚洲国产91色在线| 亚洲经典在线看| 欧美激情免费观看| 亚洲小说春色综合另类电影| 一区二区三区.www| 国产精品乱人伦一区二区| 午夜精品视频一区| 午夜精品免费| 亚洲第一黄色网| 91久久精品网| 国产精品地址| 久久久久久久久久久久久久一区| 欧美在线看片a免费观看| 亚洲成色777777女色窝| 亚洲欧洲精品一区二区三区波多野1战4| 欧美成人一区二区三区在线观看 | 亚洲国内精品在线| 亚洲缚视频在线观看| 欧美精品免费在线| 亚洲欧美日韩精品一区二区| 亚洲免费影视第一页| 在线精品国产欧美| 亚洲精品免费网站| 国产精品日日做人人爱| 欧美91精品| 欧美日韩中文字幕| 久久国产精品99国产精| 麻豆av一区二区三区久久| 亚洲视频在线视频| 久久精品99| 99精品视频免费在线观看| 亚洲女女女同性video| 亚洲第一久久影院| 欧美www视频在线观看| 精品不卡视频| 亚洲人体大胆视频| 国产精品在线看| 欧美风情在线| 国产精品丝袜久久久久久app| 麻豆精品一区二区av白丝在线| 欧美va天堂va视频va在线| 中文在线一区| 久久中文字幕一区二区三区| 日韩一二三区视频| 欧美在线免费观看| 亚洲欧美亚洲| 欧美成人精品在线| 久久一区二区三区av| 国产精品色婷婷| 亚洲日韩成人| 樱桃成人精品视频在线播放| 亚洲色图自拍| 亚洲特黄一级片| 免费的成人av| 久久综合给合| 国产一区999| 亚洲永久精品大片| 亚洲视频一二区| 欧美大片一区二区| 欧美高清在线一区二区| 国产亚洲一区二区三区在线播放| 一区二区三区免费观看| 日韩视频永久免费观看| 免费一级欧美片在线播放| 欧美成人dvd在线视频| 国产欧美日韩视频| 亚洲欧美高清| 先锋影音国产精品| 欧美午夜精品久久久久久人妖| 亚洲精品一二区| 日韩亚洲欧美精品| 欧美日韩一区二区在线观看| 日韩亚洲视频| 亚洲欧美成aⅴ人在线观看| 欧美日韩国产三级| 亚洲精品国产精品乱码不99按摩| 亚洲国产精品一区二区第四页av| 香蕉尹人综合在线观看| 久久人人爽人人爽爽久久| 韩国视频理论视频久久| 久久岛国电影| 欧美高清视频www夜色资源网| 亚洲国产精品美女| 欧美激情精品久久久久久| 亚洲精品永久免费精品| 一本大道av伊人久久综合| 欧美日韩亚洲一区二区三区在线| 亚洲精品在线看| 午夜欧美不卡精品aaaaa| 国产欧美精品va在线观看| 欧美影院成年免费版| 久久午夜电影| 亚洲国产黄色片| 欧美日韩午夜激情| 午夜欧美理论片| 久久亚洲不卡| 亚洲精品社区| 国产精品视频成人| 久久久久久有精品国产| 亚洲电影免费在线| 亚洲影院高清在线| 红桃视频成人| 亚洲精品在线观| 午夜国产不卡在线观看视频| 久久精品一级爱片| 亚洲人精品午夜| 国产精品无码永久免费888| 欧美一区亚洲一区| 亚洲人成欧美中文字幕| 欧美亚洲视频| 亚洲黄色av一区| 欧美午夜精品久久久久久久| 欧美中文字幕在线| 亚洲黄色成人久久久| 午夜免费电影一区在线观看 | 亚洲精品国产拍免费91在线| 欧美四级在线| 久久精品主播| 一本大道久久a久久精品综合| 久久亚洲一区二区| 亚洲欧美国产精品va在线观看| 亚洲丰满少妇videoshd| 国产欧美一区二区三区另类精品| 麻豆成人av| 欧美伊人久久久久久久久影院 | 午夜国产欧美理论在线播放| 亚洲国产老妈| 久久久久久久999| 亚洲午夜精品一区二区三区他趣| 国内精品久久久久久久97牛牛| 欧美精品在线免费| 久久久.com| 欧美一级淫片播放口| 亚洲午夜电影| 亚洲精品美女91| 欧美国产先锋|