static_cast一般用來將枚舉類型轉換成整型,或者整型轉換成浮點型。也可以用來將指向父類的指標轉換成指向子類的指標。做這些轉換前,你必須確定要轉換的資料確實是目標類型的資料,因為static_cast不做運行時的類型檢查以保證轉換的安全性。也因此,static_cast不如dynamic_cast安全。對含有二義性的指標,dynamic_cast會轉換失敗,而static_cast卻直接且粗暴地進行轉換。這是非常危險的。
比如:
class B {};class D : public B {};void f(B* pb, D* pd) { D* pd2 = static_cast<D*>(pb); // Not safe, D can have fields // and methods that are not in B. B* pb2 = static_cast<B*>(pd); // Safe conversion, D always // contains all of B.}
上面的第一個類型轉換是不安全的。比如,一旦使用pd2調用了一個子類D有而父類B沒有的方法,則程式就會因越界訪問而崩潰。
static_cast和dynamic_cast都可以用於類階層中基類和子類之間指標或引用的轉換。所不同的是,static_cast僅僅是依靠類型轉換語句中提供的資訊(角括弧中的類型)來進行轉換;而dynamic_cast則會遍曆整個類的繼承體系進行類型檢查。比如:
class B {public: virtual void Test(){}};class D : public B {};void f(B* pb) { D* pd1 = dynamic_cast<D*>(pb); D* pd2 = static_cast<D*>(pb);}
如果pb確實是指向一個D類型的對象,那pd1和pd2的值是相同的,即使pb為NULL。
如果pb實際指向的是一個B類型的對象,那dynamic_cast就會轉換失敗,並返回NULL(此時pd1為NULL);而static_cast卻依據程式員指定的類型簡單地返回一個指標指向假定的D類型的對象(此時pd2不為NULL),這當然是錯誤的。
static_cast還可以在兩個類對象之間進行轉換,比如把類型為A的對象a,轉換為類型為B的對象。如下:
class A;class B;A a;B b;b = static_cast<B>(a);
此過程可以看做是以a為參數構造一個B類型的臨時對象,然後再把這個臨時對象賦值給b。如下:
class A;class B;A a;B b;B c(a);b = c;
所以,如果讓以上代碼通過編譯,那麼B類必須含有以A類的對象(或對象的引用)為參數的建構函式。如下:
B(A& a){// ...}
這實際上是把轉換的工作交給建構函式去做了。
static_cast最常用的是基本類型直接的轉換,比如char與int、int與float、enum與int之間的轉換。在把int轉換為char時,如果char沒有足夠的位元位來存放int的值(int>127或int<-127時),那麼static_cast所做的只是簡單的截斷,及簡單地把int的低8位複製到char的8位中,並直接拋棄高位。在把int轉換為enum時,如果int的值沒有落進enum的範圍內,則enum的值將是“未定義”的。比如,定義一個枚舉類型Week,它包含周一到周日七天:
enum Week{Monday = 1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};
此時如果把值為8的int轉換為week類型,那麼這個Week變數不會是周一到周日的任何一天。
Week noday = static_cast<Week>(8);
如果你用“%d”格式把它列印出來,你會發現,它的值確實是8。但這已經超出周一到周日了。世界上沒有“星期八”,不是嗎?
static_cast甚至可以把任何一個運算式轉換為void類型。
再次提醒,static_cast完全靠程式員自己去保證轉換的正確性。
static_cast轉換的目標類型可以帶const、volatile或__unaligned屬性。但static_cast不能把源類型的這些熟悉移除。如果想強制移除一個變數的const、volatile或__unaligned屬性,請參考const_cast操作符。
小結一下:
static_cast常用來進行基本類型直接的轉換,如char與int、int與float、enum與int之間;
static_cast也可以轉換使用者自訂類型,但目標類型必須含有相應的建構函式;
static_cast還可以轉換對象的指標類型,但它不進行運行時類型檢查,所以是不安全的;
static_cast甚至可以把任何錶達式都轉換成void類型;
satic_cast不能移除變數的const屬性,請參考const_cast操作符;一個比較好的例子可見:http://blog.csdn.net/sinshine/article/details/6743454
static_cast進行的是簡單粗暴的轉換,所以其正確性完全由程式員自己保證。
以上是轉載。下面舉個自己的例子用到了static_cast。
下面的類roi_preprocess_filter作為基類。裡面init函數的參數是空的結構體preproc_params。
struct preproc_params { }; //any preprocessing like gray histogram, low or high //pass filter should inherit this interface class roi_preprocess_filter { public: virtual void init( const preproc_params& params ) = 0;。。。。。 };
在子類中可以定義如下:
struct dog_params:preproc_params { double sigma1; double sigma2; dog_params( double sig1=0., double sig2=0. ); };
class roi_diff_gauss_filter: public roi_preprocess_filter { public: virtual void init( const preproc_params& params ); protected: dog_params m_dog_params; };
void roi_diff_gauss_filter::init( const preproc_params& params ) { m_dog_params = static_cast< const dog_params& >( params );//這裡利用static_cast來強制轉換 }