C 中的執行時型別檢查

2021-07-17 02:43:53 字數 3638 閱讀 5531

c++中的執行時型別檢查

簡介經常有人問到:「我怎樣才能在執行時確定或檢查c++中物件的型別呢?」,下面通過乙個簡單問題來作一演示。

以下程式會在第一次呼叫cfoo::animalsays 時顯示「bark!」,而第二次呼叫時顯示「miaou」。

class animal ;

class dog : public animal ;

class cat : public animal ;

class cfoo

};int main(int argc, char* argv)

也就是說,你需要用某種方法在執行時來確定函式 cfoo::animalsays接受的引數,到底是指向dog型別物件的指標,還是指向cat型別物件的指標。

第一次嘗試

我們的第乙個想法是新增乙個成員變數,其儲存了型別的相關資訊。

#include

class animal;};

class dog : public animal

const animaltype m_type;

};class cat : public animal

const animaltype m_type;

};class cfoo

;int main(int argc, char* argv)

void cfoo::animalsays(animal* panimal)

現在,回過頭看一下 cfoo::animalsays函式的實現部分,試想我們如果不只有兩種動物型別,而是50多種呢(也就是說,從animal的派生類)?這樣一來,不但**非常難看,還很難保證不出錯,也難於閱讀、修改、維護,這可不是乙個好的解決方案。

另乙個好點的方法

在靜態成員變數中儲存類名,通過虛函式來訪問。

#include

#include

class animal

;class dog : public animal

;class cat : public animal

;class cfoo

;int main(int argc, char* argv)

const string  dog::m_class_name = "dog";

const string  cat::m_class_name = "cat";

bool dog::isoftype(const std::string& class_name)

bool cat::isoftype(const std::string& class_name)

void cfoo::animalsays(animal* panimal)

cfoo::animalsays現在看上去乾淨多了,比前一種方法也易於閱讀,但還能新增兩個巨集來進一步簡化**:

#include

#include

#define declare_runtime_class /

private: static const std::string m_class_name; /

public: virtual bool isoftype(const std::string&);

#define implement_runtime_class(class_name) /

const std::string class_name##::m_class_name = #class_name; /

bool class_name##::isoftype(const std::string& name) /

// ...

這樣一來,以後就能新增更小的**塊了。

// ...

class animal

;class dog : public animal

;class cat : public animal

;class cfoo

;int main(int argc, char* argv)

implement_runtime_class(dog)

implement_runtime_class(cat)

void cfoo::animalsays(animal* panimal)

現在,已經非常接近mfc的解決方案了。

如果使用mfc,這種問題簡直是「小菜一碟」。大多數mfc類派生自cobject,而cobject連同一些新的mfc巨集都新增了對執行時型別資訊的支援,解決上述問題的mfc辦法就是將你的類置於mfc繼承體系之中,並使用相對應的巨集,如下所示:

#include

class animal : public cobject

;class dog : public animal

;class cat : public animal

;class cfoo

;int main(int argc, char* argv)

implement_dynamic(animal, cobject)

implement_dynamic(dog, animal)

implement_dynamic(cat, animal)

void cfoo::animalsays(animal* panimal)

另一種方法:rtti

c++內建的執行時型別檢查機制為rtti(run-time type information),rtti允許使用兩個操作符:typeid與dynamic_cast。用rtti解決上述問題的第一種方法是使用typeid,它返回乙個對type_info物件的引用,其儲存了傳遞進來的物件型別資訊。

#include

class animal ;};

class dog : public animal{};

class cat : public animal{};

class cfoo

;int main(int argc, char* argv)

void cfoo::animalsays(animal* panimal)

第二種方法是使用dynamic_cast,如果你傳遞給它乙個所不期望型別的指標,它將返回0,程式如下面這樣:

void cfoo::animalsays(animal* panimal)

注意,類animal至少必須有乙個虛函式。為什麼?因為如果你的類不是「多種型別」的,rtti機制不會正常工作。另外,rtti需從「專案設定——屬性」中開啟,預設是關閉的。譯者注:visual c++ 2008 sp1中在「專案屬性——配置屬性——c/c++——語言」下,預設是開啟的。

最後,真的需要它嗎?

乙個設計良好、用於多型的類,是無須擔心執行時型別檢查的,在本文這個特例中,可在抽象基類(animal)中放置乙個純虛函式isay,並為每個派生者新增一些具體的實現。

#include

class animal

;class dog : public animal

};class cat : public animal

};class cfoo

;int main(int argc, char* argv)

void cfoo::animalsays(animal* panimal)

看一下cfoo::animalsays函式,它非常清爽、簡潔,無需執行時型別檢查。

結論既可用rtti,也可用像mfc機制的方法來實現執行時型別檢查,但恐怕也沒什麼必要。

執行時型別檢查

執行時型別資訊 run time type information 通常記做rtti。在c primer第五版中,譯作執行型別識別 run time type identification 執行時型別資訊包括三部分 1 乙個運算子dynamic cast,給它乙個指向某某物件的基類指標,它能得到乙個...

RTTI 執行時型別檢查 虛函式

在c 層面主要體現在dynamic cast和typeid,vs中虛函式表的 1位置存放了指向type info的指標。對於存在虛函式的型別,typeid和dynamic cast都會去查詢type info rtti即執行時型別識別,用來識別動態物件的型別。即使我們僅僅有基類的指標和引用,可以識別...

C 關鍵字typeid 執行時型別檢查

在揭開typeid神秘面紗之前,我們先來了解一下 rtti run time type identification,執行時型別識別 它使程式能夠獲取由基指標或引用所指向的物件的實際派生型別,即允許 用指向基類的指標或引用來操作物件 的程式能夠獲取到 這些指標或引用所指物件 的實際派生型別。在c 中...