我想知道什麼是靜態和動態類型檢查以及它們之間的差異。C++中的靜態和動態類型檢查
回答
靜態類型檢查意味着類型檢查在編譯時發生。在這種情況下,在運行時不會使用類型信息。
在運行時使用類型信息時會發生動態類型檢查。 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。
值得注意的是,static_cast在上面簡單的示例中完全有效。只有在您不確定Shape是Circle類型時才應該使用dynamic_cast,在這種情況下,dynamic_cast將返回NULL(或者在投射參考時拋出異常)。 – 2009-08-29 04:59:03
靜態類型檢查是在編譯時完成的類型檢查。這是C++檢查類型的唯一類型。動態類型檢查是在運行時完成的類型檢查。這通常在動態解釋語言中看到,但在編譯語言中不常見。最後我檢查了一下,C++沒有做任何動態類型檢查。
編輯:顯然我過時了。請參閱下面的裏德評論。
dynamic_cast存在於C++中,並且在許多C++運行時上運行時間類型檢查。 – 2009-08-28 15:36:16
我糾正:)謝謝! – 2009-08-28 15:44:12
在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
「B * b = static_cast (a); // This will will!」:你不應該更好地評論這個:「這樣會編譯,你得到一個非NULL指針;但它不一定能工作! – mmmmmmmm 2009-08-28 17:01:03
我認爲其實static_cast只適用於相關類型,並會拒絕編譯,在這種情況下需要reinterpret_cast。這些例子看起來都搞砸了我。 – 2009-08-28 17:44:55
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;
}
假設你有:
class A {};
class B:A {};
A* a = new B();
B* b = new B();
對於靜態類型,你看看變量的聲明方式。
A* a = ...
B* b = ...
所以靜態類型的a
是A*
(或者換一種說法,靜態類型的*a
爲A
)。
和靜態類型的b
是B*
(或者換一種說法,靜態類型的*b
是B
)。
請注意,a
和b
有一個靜態類型,通過它的聲明來修復 - 它們放在它們中並不重要,它們將保持相同的靜態類型。 (「靜態」意味着「不變」)。
對於動態類型,您可以看看現在變量中會發生什麼。
a = new B();
b = new B();
所以動態類型的a
和b
都是B*
(或者換一種方式,動態類型的*a
和*b
都是B
)。
請注意,動態類型可以更改 - 如果你做了a = new A()
那麼他們的動態類型a
只是更改爲A*
。有時你不知道動態類型是什麼 - 例如如果你這樣做a = somefunc()
然後a
可能有動態類型A*
B*
或甚至C*
(如果您沒有看到一些代碼定義C
作爲A
或B
的子類)。
如果A
有一個virtual
方法,那麼你可以使用dynamic_cast
找出動態類型是什麼。 (通常,如果你使用的是這種代碼,你希望能夠做到delete a
;爲了這個工作,A
的析構函數必須是virtual
。而使A
的析構函數虛擬就足以讓dynamic_cast
工作)。
c'mon ...第3谷歌:http://www.sitepoint.com/article/typing-versus-dynamic-typing/ ...這個代表計劃的事情真的贊助提出所有類型的問題。 ..>嘆息< – jpinto3912 2009-08-28 18:04:03
stackoverflow的目標是成爲所有編程知識的存儲庫,即使它存在於其他地方。 – 2009-08-28 23:02:27
我知道它在谷歌的某個地方,但在這裏你得到多個定義,它可以幫助你以更清晰的方式進行理解 – rkb 2009-08-31 17:14:27