標籤:everyone 情況 ever blog 不能 log rom logs class
情境:
1. C++的對象差別於C的原因是他們能夠有繼承關係, 方法有重載, 覆蓋關係等, 他們的對象記憶體資料結構因此也比較複雜.
2. 非常多情況下我們須要一個父類來儲存子類的指標對象進行通用方法的操作。涉及到詳細某個子類對象特定操作時又須要強制轉換為子類。那麼這時候該用什麼好呢?
答: 假設不須要類型檢查的話就直接用C的強制轉換就可以(B*)c. 可是C++ 之父並不推薦使用C的強制類型轉換;
原因1是沒有編譯器檢查.
原因2是對象指標在子類父類之間轉換時所相應的地址值可能會變化, 這樣用C的轉換會有誤導的可能在那裡.
看範例和凝視說明吧:
test.cpp
#include <iostream>class A{public:A(){}~A(){}int i;int j1;void Test(){ std::cout << "TestA" << std::endl;}/* data */};class C{public:C(){}~C(){}int j;void Test(){ std::cout << "TestC" << std::endl;}/* data */};class B : public A,public C{public:B(){}~B(){}void Test(){ std::cout << "TestB" << std::endl;}/* data */};class K{};// static_cast: 能夠進行類型上行和下行轉換,會進行類型檢查.// reinterpret_cast: 和C的強轉一樣,不做類型檢查,能夠從隨意指標類型轉換為其它指標類型,非指標類型不能轉,比方char to int.// dynimic_cast: 僅僅適用於多態的類(帶virtual)int main(int argc, char const *argv[]){A* a = new A();B* b = new B();C* c = b;std::cout << "(int*)a* :" << (int*)a << " (int)a:" << (int)a << " reinterpret_cast<int>(a):" << reinterpret_cast<int>(a) << std::endl;std::cout << "(int*)b :" << (int*)b << " (int)b:" << (int)b << " reinterpret_cast<int>(b):" << reinterpret_cast<int>(b) << std::endl;// 1.這裡假設把c轉換為(K*)c,編譯不會報錯,可是假設使用static_cast<K*>編譯會報錯.// 由於static_cast會進行上行的類型檢查. // 注意: 這裡(int*)c的地址和上邊的(int*)b地址是不一樣的,由於他們不是多態關係,並且A,C有成員變數,因此會有位移量.(沒有virtual)std::cout << "(int*)c :" << (int*)c << " (int)c:" << (int)c << " reinterpret_cast<int>(c):" << reinterpret_cast<int>(c) << " (B*)c: " << (B*)c << " static_cast<B*>(c):" << static_cast<B*>(c) << " static_cast<C*>(b):" << static_cast<C*>(b) << std::endl; // 下面編譯會報錯,dynimc_cast不同意非多態轉換,由於沒有virtual// ////error: cannot dynamic_cast ‘c‘ (of type ‘class C*‘) to type ‘class B*‘ (source type is not polymorphic)// 假設C的建構函式加virtual的話是能夠轉的,並且帶virtual表的地址不會變.// std::cout << "c* :" << (int*)c << ":" << (int)c << ":" // << dynamic_cast<B*>(c) << ":"// << std::endl; return 0;}
輸出:
(int*)a* :0x2c64e0 (int)a:2909408 reinterpret_cast<int>(a):2909408(int*)b :0x2c2378 (int)b:2892664 reinterpret_cast<int>(b):2892664(int*)c :0x2c2380 (int)c:2892672 reinterpret_cast<int>(c):2892672 (B*)c: 0x2c2378 static_cast<B*>(c):0x2c2378 static_cast<C*>(b):0x2c2380
所以你看到下面static_cast的使用方法不要認為奇怪, 它是為了使用編譯器檢查.
template<typename T> void** IID_PPV_ARGS_Helper(T** pp) { static_cast<IUnknown*>(*pp); // make sure everyone derives from IUnknown return reinterpret_cast<void**>(pp); }
參考:
http://www.cnblogs.com/chio/archive/2007/07/18/822389.html
[C/C++]_[0基礎]_[static_cast,reinterpret_cast,dynimic_cast的使用情境和差別]