static_cast & dynamic_cast

來源:互聯網
上載者:User

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來強制轉換        }


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.