C++标准转换运算符static_cast
C++標準轉換運算符static_cast
static_cast <new_type> (expression)
雖然const_cast是用來去除變量的const限定,但是static_cast卻不是用來去除變量的static引用。其實這是很容易理解的,static決定的是一個變量的作用域和生命周期,比如:在一個文件中將變量定義為static,則說明這個變量只能在本Package中使用;在方法中定義一個static變量,該變量在程序開始存在直到程序結束;類中定義一個static成員,該成員隨類的第一個對象出現時出現,并且可以被該類的所有對象所使用。
對static限定的改變必然會造成范圍性的影響,而const限定的只是變量或對象自身。但無論是哪一個限定,它們都是在變量一出生(完成編譯的時候)就決定了變量的特性,所以實際上都是不容許改變的。這點在const_cast那部分就已經有體現出來。
static_cast和reinterpret_cast一樣,在面對const的時候都無能為力:兩者都不能去除const限定。兩者也存在的很多的不同,比如static_cast不僅可以用在指針和引用上,還可以用在基礎數據和對象上;前面提到過reinterpret_cast可以用在"沒有關系"的類型之間,而用static_cast來處理的轉換就需要兩者具有"一定的關系"了。
還是用例子來說明比較直觀一些。
還是用例子來說明比較直觀一些。
在reinterpret_cast一篇,已經提到過reinterpret_cast可以在任意指針之間進行互相轉換,即使這些指針所指的內容是毫無關系的,也就是說一下語句,編譯器是不會報錯的,但是對于程序來說也是毫無意義可言的,只會造成程序崩潰:
#include <iostream> using namespace std; unsigned short Hash( void *p ) {unsigned long val = reinterpret_cast<unsigned long>( p );return ( unsigned short )( val ^ (val >> 16)); }class Something {/* Some codes here */ };class Otherthing {/* Some codes here */ };int main() {typedef unsigned short (*FuncPointer)( void *) ;FuncPointer fp = Hash; //right, this is what we wantint a[10];const int* ch = a; //right, array is just like pointerchar chArray[4] = {'a','b','c','d'};fp = reinterpret_cast<FuncPointer> (ch); //no error, but does not make sensech = reinterpret_cast<int*> (chArray); //no errorcout <<hex<< *ch; //output: 64636261 //it really reinterpret the pointerSomething * st = new Something();Otherthing * ot = reinterpret_cast<Otherthing*> (st); //cast between objects with on relationship }而以上轉換,都是static_cast所不能完成的任務,也就是說把上邊程序里所有的reinterpret_cast換成static_cast的話,就會立即得到編譯錯誤,因為目標指針和原始指針之間不存在"關系"
從上邊的程序,也就一下子看出來了reinterpret_cast和static_cast之間最本質的區別。
而以上轉換,都是static_cast所不能完成的任務,也就是說把上邊程序里所有的reinterpret_cast換成static_cast的話,就會立即得到編譯錯誤,因為目標指針和原始指針之間不存在"關系"
從上邊的程序,也就一下子看出來了reinterpret_cast和static_cast之間最本質的區別。
對于static_cast所需要的關系,"繼承"絕對是其中之一,所以static_cast支持指向基類的指針和指向子類的指針之間的互相轉換:
class Parents { public:virtual ~Parents(){}/*codes here*/ };class Children : public Parents {/*codes here*/ };int main() { Children * daughter = new Children();Parents * mother = static_cast<Parents*> (daughter); //right, cast with polymorphismParents * father = new Parents();Children * son = static_cast<Children*> (father); //no error, but not safe }但是從基類到子類的轉換,用static_cast并不是安全的,具體的問題會在dynamic_cast一篇闡述。
在指針和引用方便,似乎也只有繼承關系是可以被static_cast接受的,其他情況的指針和引用轉換都會被static_cast直接扔出編譯 錯誤,而這層關系上的轉換又幾乎都可以被dynamic_cast所代替。這樣看起來static_cast運算符的作用就太小了。
實際上static_cast真正用處并不在指針和引用上,而在基礎類型和對象的轉換上 。 而基于基礎類型和對象的轉換都是其他三個轉換運算符所辦不到的。
這些轉換跟C++用戶自定義類型轉換一文中所設計的內容比較接近,所以在那邊文章中出現轉換可以全部加上static_cast。
基礎類型轉換:
float floatValue = 21.7;
int intValue = 7;
cout << floatValue / 7 << "\t\t" << static_cast<int> (floatValue)/7 <<endl;
cout << intValue/3 << "\t\t" << static_cast<double> (intValue)/3 << endl;
//Output:
//3.1?????3
//2???????2.33333
從輸出結果可以看出轉換是成功并且正確的。
對于對象的轉換,也是需要又關系的,這層關系就是C++用戶自定義類型轉換中提到的方法:
- 構造函數(Constructor)
- 類型轉換運算符(Type –Cast Operator
static_cast會根據上述順序尋找到合適的方法進行類型轉換。
賦值運算符并不被算在內,因為它自身已經是一種運算符,不能再當做轉換運算符來用。
int main(void) {Ape a;Human h = static_cast<Human> (a); // using promtion constructorProgrammer p;p = static_cast<Programmer> (h); // using Programmer-cast operaotor//Ape a2;//a2 = static_cast<Ape> (p); //Error, assignment operator should be used directlyreturn 0; }(類的代碼見C++用戶自定義類型轉換,或者下載代碼查看)
傳統轉換方式實現static_cast運算符
從上邊對static_cast分析可以跟看,static_cast跟傳統轉換方式幾乎是一致的,所以只要將static_cast和圓括號去掉,再將尖括號改成圓括號就變成了傳統的顯示轉換方式。在C++用戶自定義類型轉換一文已有很多的介紹了。
Director:?Jim Fawcett轉載于:https://www.cnblogs.com/Cmpl/archive/2011/09/02/2164385.html
總結
以上是生活随笔為你收集整理的C++标准转换运算符static_cast的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android笔记3:activity的
- 下一篇: WCF常见问题及解决方案