C++標準轉換運算符static_cast

static_cast (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 want


	int a[10];
	const int* ch = a; //right, array is just like pointer
	char chArray[4] = {'a','b','c','d'};
	fp = reinterpret_cast<FuncPointer> (ch); //no error, but does not make sense
	ch = reinterpret_cast<int*> (chArray);	//no error
	
	cout <<hex<< *ch;	//output: 64636261	//it really reinterpret the pointer


	
	Something * 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支持指向基類的指針和指向子類的指針之間的互相轉換:





但是從基類到子類的轉換,用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 constructor


	Programmer p;
	p = static_cast<Programmer> (h); // using  Programmer-cast operaotor


	//Ape a2;
	//a2 = static_cast<Ape> (p); //Error, assignment operator should be used directly


	return 0;
}



(類的代碼見C++用戶自定義類型轉換,或者下載代碼查看)
傳統轉換方式實現static_cast運算符


從上邊對static_cast分析可以跟看,static_cast跟傳統轉換方式幾乎是一致的,所以只要將static_cast和圓括號去掉,再將尖括號改成圓括號就變成了傳統的顯示轉換方式。在C++用戶自定義類型轉換一文已有很多的介紹了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章