2009-08-28 101 views
7

我想知道什麼是靜態和動態類型檢查以及它們之間的差異。C++中的靜態和動態類型檢查

+2

c'mon ...第3谷歌:http://www.sitepoint.com/article/typing-versus-dynamic-typing/ ...這個代表計劃的事情真的贊助提出所有類型的問題。 ..>嘆息< – jpinto3912 2009-08-28 18:04:03

+7

stackoverflow的目標是成爲所有編程知識的存儲庫,即使它存在於其他地方。 – 2009-08-28 23:02:27

+7

我知道它在谷歌的某個地方,但在這裏你得到多個定義,它可以幫助你以更清晰的方式進行理解 – rkb 2009-08-31 17:14:27

回答

15

靜態類型檢查意味着類型檢查在編譯時發生。在這種情況下,在運行時不會使用類型信息。

在運行時使用類型信息時會發生動態類型檢查。 C++使用稱爲RTTI(運行時類型信息)的機制來實現這一點。在使用RTTI最常見的例子是dynamic_cast運算符,它允許多態類型的向下轉換:

// assuming that Circle derives from Shape... 
Shape *shape = new Circle(50); 
Circle *circle = dynamic_cast<Circle*> shape; 

此外,還可以使用typeid操作符,瞭解運行時類型的對象。例如,您可以使用它來檢查示例中的形狀是圓形還是矩形。這裏有一些further information

+3

值得注意的是,static_cast在上面簡單的示例中完全有效。只有在您不確定Shape是Circle類型時才應該使用dynamic_cast,在這種情況下,dynamic_cast將返回NULL(或者在投射參考時拋出異常)。 – 2009-08-29 04:59:03

0

靜態類型檢查是在編譯時完成的類型檢查。這是C++檢查類型的唯一類型。動態類型檢查是在運行時完成的類型檢查。這通常在動態解釋語言中看到,但在編譯語言中不常見。最後我檢查了一下,C++沒有做任何動態類型檢查。

編輯:顯然我過時了。請參閱下面的裏德評論。

+8

dynamic_cast存在於C++中,並且在許多C++運行時上運行時間類型檢查。 – 2009-08-28 15:36:16

+0

我糾正:)謝謝! – 2009-08-28 15:44:12

2

在C++中有多種類型的強制轉換。

最常見的情況是使用static_cast來將一種類型的指針變量轉換爲另一種類型的指針。但是,您也可以使用dynamic_cast,它將檢查以確保(在運行時)指針的類型正確。對於dynamic_cast,如果指針不是正確的類型,那麼在運行時它將返回0。

// Assume these classes exist 
// class A 
// class B 
// class C : B 

C* c = new C(); 
A* a = new A(); 

B* b = static_cast<B*>(a); // this will work! 
b = dynamic_cast<B*>(a); // b == NULL 
b = dynamic_cast<B*>(c); // b is valid 
+0

「B * b = static_cast (a); // This will will!」:你不應該更好地評論這個:「這樣會編譯,你得到一個非NULL指針;但它不一定能工作! – mmmmmmmm 2009-08-28 17:01:03

+0

我認爲其實static_cast只適用於相關類型,並會拒絕編譯,在這種情況下需要reinterpret_cast。這些例子看起來都搞砸了我。 – 2009-08-28 17:44:55

3

C++有動態類型檢查一個非常小的支撐是通過dynamic_cast和另一種是通過type id。既可以僅當RTTI支撐在編譯器被使能使用。

TYPE& dynamic_cast<TYPE&> (object); 
TYPE* dynamic_cast<TYPE*> (object); 

的dynamic_cast的關鍵字蒙上了基準從一個指針或引用類型到另一個,執行運行時檢查以確保鑄造的有效性。

如果您嘗試轉換爲不是實際對象類型的類型的指針,則轉換的結果將爲NULL。如果您嘗試轉換爲引用不是實際對象類型的類型,則該轉換將引發bad_cast異常。

確保基類中至少有一個虛擬函數可以使動態廣播工作。

// expre_typeid_Operator.cpp 
// compile with: /GR /EHsc 
#include <iostream> 
#include <typeinfo.h> 

class Base { 
public: 
    virtual void vvfunc() {} 
}; 

class Derived : public Base {}; 

using namespace std; 
int main() { 
    Derived* pd = new Derived; 
    Base* pb = pd; 
    cout << typeid(pb).name() << endl; //prints "class Base *" 
    cout << typeid(*pb).name() << endl; //prints "class Derived" 
    cout << typeid(pd).name() << endl; //prints "class Derived *" 
    cout << typeid(*pd).name() << endl; //prints "class Derived" 
    delete pd; 
} 
2

假設你有:

class A {}; 
class B:A {}; 

A* a = new B(); 
B* b = new B(); 

對於靜態類型,你看看變量的聲明方式。

A* a = ... 
B* b = ... 

所以靜態類型的aA*(或者換一種說法,靜態類型的*aA)。

和靜態類型的bB*(或者換一種說法,靜態類型的*bB)。

請注意,ab有一個靜態類型,通過它的聲明來修復 - 它們放在它們中並不重要,它們將保持相同的靜態類型。 (「靜態」意味着「不變」)。


對於動態類型,您可以看看現在變量中會發生什麼。

a = new B(); 
b = new B(); 

所以動態類型的ab都是B*(或者換一種方式,動態類型的*a*b都是B)。

請注意,動態類型可以更改 - 如果你做了a = new A()那麼他們的動態類型a只是更改爲A*。有時你不知道動態類型是什麼 - 例如如果你這樣做a = somefunc()然後a可能有動態類型A*B*或甚至C*(如果您沒有看到一些代碼定義C作爲AB的子類)。

如果A有一個virtual方法,那麼你可以使用dynamic_cast找出動態類型是什麼。 (通常,如果你使用的是這種代碼,你希望能夠做到delete a;爲了這個工作,A的析構函數必須是virtual。而使A的析構函數虛擬就足以讓dynamic_cast工作)。