C++指針類型與強制轉換

C++ 指針類型

指針,用來描述內存地址,並通過提供指針操作來實現與內存相關的程序功能。

指針是一個特殊數據類型,也可以理解爲混合數據類型。指針具有數據類型信息及數據在內存空間的地址。

 

C++指針的類型轉換

問題的由來:當我們想打印指針地址時,或是某些需求想得到地址值時,我們必須轉化爲字符類型給顯示組件。比如label等等。。。

問題分析:C++指針雖然像int類型或是long int類型一樣存放着內存地址。但是我們取得的指針地址,不僅僅只有地址值,因爲指針類型是一種混合類型。這時我們就需要強制類型轉換。我在QT 5.14版本編譯器環境中,要求必須使用long long int,否則會提示接納變量類型位數不足,不能容納指針地址。這時因爲不同的系統,不同的地址容量,所造成的地址長度不同。比如32位系統的地址長度要比64位的地址長度短。

 

C++強制類型轉換運算符(static_cast、reinterpret_cast、const_cast和dynamic_cast)

將類型名作爲強制類型轉換運算符的做法是C語言的老式做法,C++ 爲保持兼容而予以保留。但是,最新的編譯器會給出警告。對於有強迫症的人來說是無法忍受的。

C++ 引入了四種功能不同的強制類型轉換運算符以進行強制類型轉換:static_cast、reinterpret_cast、const_cast 和 dynamic_cast。

強制類型轉換是有一定風險的,有的轉換並不一定安全,如把整型數值轉換成指針,把基類指針轉換成派生類指針,把一種函數指針轉換成另一種函數指針,把常量指針轉換成非常量指針等。C++ 引入新的強制類型轉換機制,主要是爲了克服C語言強制類型轉換的以下三個缺點:

1) 沒有從形式上體現轉換功能和風險的不同。

例如,將 int 強制轉換成 double 是沒有風險的,而將常量指針轉換成非常量指針,將基類指針轉換成派生類指針都是高風險的,而且後兩者帶來的風險不同(即可能引發不同種類的錯誤),C語言的強制類型轉換形式對這些不同並不加以區分。

2) 將多態基類指針轉換成派生類指針時不檢查安全性,即無法判斷轉換後的指針是否確實指向一個派生類對象。

3) 難以在程序中尋找到底什麼地方進行了強制類型轉換。

強制類型轉換是引發程序運行時錯誤的一個原因,因此在程序出錯時,可能就會想到是不是有哪些強制類型轉換出了問題。

如果採用C語言的老式做法,要在程序中找出所有進行了強制類型轉換的地方,顯然是很麻煩的,因爲這些轉換沒有統一的格式。

而用 C++ 的方式,則只需要查找_cast字符串就可以了。甚至可以根據錯誤的類型,有針對性地專門查找某一種強制類型轉換。例如,懷疑一個錯誤可能是由於使用了 reinterpret_cast 導致的,就可以只查找reinterpret_cast字符串。

C++ 強制類型轉換運算符的用法如下:

強制類型轉換運算符 <要轉換到的類型> (待轉換的表達式)

 

static_cast

static_cast 用於進行比較“自然”和低風險的轉換,如整型和浮點型、字符型之間的互相轉換。另外,如果對象所屬的類重載了強制類型轉換運算符 T(如 T 是 int、int* 或其他類型名),則 static_cast 也能用來進行對象到 T 類型的轉換。

static_cast 不能用於在不同類型的指針之間互相轉換,也不能用於整型和指針之間的互相轉換,當然也不能用於不同類型的引用之間的轉換。因爲這些屬於風險比較高的轉換。

 

reinterpret_cast

reinterpret_cast 用於進行各種不同類型的指針之間、不同類型的引用之間以及指針和能容納指針的整數類型之間的轉換。轉換時,執行的是逐個比特複製的操作。

這種轉換提供了很強的靈活性,但轉換的安全性只能由程序員的細心來保證了。例如,程序員執意要把一個 int* 指針、函數指針或其他類型的指針轉換成 string* 類型的指針也是可以的,至於以後用轉換後的指針調用 string 類的成員函數引發錯誤,程序員也只能自行承擔查找錯誤的煩瑣工作:(C++ 標準不允許將函數指針轉換成對象指針,但有些編譯器,如 Visual Studio 2010,則支持這種轉換)。

reinterpret_cast體現了 C++ 語言的設計思想:用戶可以做任何操作,但要爲自己的行爲負責。

 

const_cast

const_cast 運算符僅用於進行去除 const 屬性的轉換,它也是四個強制類型轉換運算符中唯一能夠去除 const 屬性的運算符。

將 const 引用轉換爲同類型的非 const 引用,將 const 指針轉換爲同類型的非 const 指針時可以使用 const_cast 運算符。

 

dynamic_cast

用 reinterpret_cast 可以將多態基類(包含虛函數的基類)的指針強制轉換爲派生類的指針,但是這種轉換不檢查安全性,即不檢查轉換後的指針是否確實指向一個派生類對象。dynamic_cast專門用於將多態基類的指針或引用強制轉換爲派生類的指針或引用,而且能夠檢查轉換的安全性。對於不安全的指針轉換,轉換結果返回 NULL 指針。

dynamic_cast 是通過“運行時類型檢查”來保證安全性的。dynamic_cast 不能用於將非多態基類的指針或引用強制轉換爲派生類的指針或引用——這種轉換沒法保證安全性,只好用 reinterpret_cast 來完成。

那該如何判斷該轉換是否安全呢?不存在空引用,因此不能通過返回值來判斷轉換是否安全。C++ 的解決辦法是:dynamic_cast 在進行引用的強制轉換時,如果發現轉換不安全,就會拋出一個異常,通過處理異常,就能發現不安全的轉換。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章