C++ 强制类型转换运算符
C++ 將類型名作為強制類型轉換運算符。
C++ 引入了四種功能不同的強制類型轉換運算符以進行強制類型轉換:static_cast、reinterpret_cast、const_cast 和 dynamic_cast。
強制類型轉換是有一定風險的,有的轉換并不一定安全,如把整型數值轉換成指針,把基類指針轉換成派生類指針,把一種函數指針轉換成另一種函數指針,把常量指針轉換成非常量指針等。C++ 引入新的強制類型轉換機制,主要是為了克服C語言強制類型轉換的以下三個缺點。
1 沒有從形式上體現轉換功能和風險的不同。
例如,將 int 強制轉換成 double 是沒有風險的,而將常量指針轉換成非常量指針,將基類指針轉換成派生類指針都是高風險的,而且后兩者帶來的風險不同(即可能引發不同種類的錯誤),C語言的強制類型轉換形式對這些不同并不加以區分。
2 將多態基類指針轉換成派生類指針時不檢查安全性,即無法判斷轉換后的指針是否確實指向一個派生類對象。
3 難以在程序中尋找到底什么地方進行了強制類型轉換。
強制類型轉換是引發程序運行時錯誤的一個原因,因此在程序出錯時,可能就會想到是不是有哪些強制類型轉換出了問題。
使用 C++ 的方式,只需要查找_cast字符串就可以了。甚至可以根據錯誤的類型,有針對性地專門查找某一種強制類型轉換。例如,懷疑一個錯誤可能是由于使用了 reinterpret_cast 導致的,就可以只查找reinterpret_cast字符串。
C++ 強制類型轉換運算符的用法如下:
強制類型轉換運算符 <要轉換到的類型> (待轉換的表達式)例如:
double d = static_cast <double> (3*5); //將 3*5 的值轉換成實數下面分別介紹四種強制類型轉換運算符。
static_cast
static_cast 用于進行比較“自然”和低風險的轉換,如整型和浮點型、字符型之間的互相轉換。另外,如果對象所屬的類重載了強制類型轉換運算符 T(如 T 是 int、int* 或其他類型名),則 static_cast 也能用來進行對象到 T 類型的轉換。
static_cast 不能用于在不同類型的指針之間互相轉換,也不能用于整型和指針之間的互相轉換,當然也不能用于不同類型的引用之間的轉換。因為這些屬于風險比較高的轉換。
static_cast 用法示例如下:
#include <iostream> using namespace std; class A { public:operator int() { return 1; }operator char*() { return NULL; } }; int main() {A a;int n;char* p = "New Dragon Inn";n = static_cast <int> (3.14); // n 的值變為 3n = static_cast <int> (a); //調用 a.operator int,n 的值變為 1p = static_cast <char*> (a); //調用 a.operator char*,p 的值變為 NULLn = static_cast <int> (p); //編譯錯誤,static_cast不能將指針轉換成整型p = static_cast <char*> (n); //編譯錯誤,static_cast 不能將整型轉換成指針return 0; }reinterpret_cast
reinterpret_cast 用于進行各種不同類型的指針之間、不同類型的引用之間以及指針和能容納指針的整數類型之間的轉換。轉換時,執行的是逐個比特復制的操作。
這種轉換提供了很強的靈活性,但轉換的安全性只能由程序員的細心來保證了。例如,程序員執意要把一個 int* 指針、函數指針或其他類型的指針轉換成 string* 類型的指針也是可以的,至于以后用轉換后的指針調用 string 類的成員函數引發錯誤,程序員也只能自行承擔查找錯誤的煩瑣工作:(C++ 標準不允許將函數指針轉換成對象指針,但有些編譯器,如 Visual Studio 2010,則支持這種轉換)。
reinterpret_cast 用法示例如下:
#include <iostream> using namespace std; class A { public:int i;int j;A(int n):i(n),j(n) { } }; int main() {A a(100);int &r = reinterpret_cast<int&>(a); //強行讓 r 引用 ar = 200; //把 a.i 變成了 200cout << a.i << "," << a.j << endl; // 輸出 200,100int n = 300;A *pa = reinterpret_cast<A*> ( & n); //強行讓 pa 指向 npa->i = 400; // n 變成 400pa->j = 500; //此條語句不安全,很可能導致程序崩潰cout << n << endl; // 輸出 400long long la = 0x12345678abcdLL;pa = reinterpret_cast<A*>(la); //la太長,只取低32位0x5678abcd拷貝給paunsigned int u = reinterpret_cast<unsigned int>(pa);//pa逐個比特拷貝到ucout << hex << u << endl; //輸出 5678abcdtypedef void (* PF1) (int);typedef int (* PF2) (int,char *);PF1 pf1; PF2 pf2;pf2 = reinterpret_cast<PF2>(pf1); //兩個不同類型的函數指針之間可以互相轉換 }程序的輸出結果是:
200, 100 400 5678abed上面程序中的各種轉換都沒有實際意義,只是為了演示 reinteipret_cast 的用法而已。在編寫黑客程序、病毒或反病毒程序時,也許會用到這樣怪異的轉換。
reinterpret_cast體現了 C++ 語言的設計思想:用戶可以做任何操作,但要為自己的行為負責。
const_cast
const_cast 運算符僅用于進行去除 const 屬性的轉換,它也是四個強制類型轉換運算符中唯一能夠去除 const 屬性的運算符。
將 const 引用轉換為同類型的非 const 引用,將 const 指針轉換為同類型的非 const 指針時可以使用 const_cast 運算符。例如:
const string s = "Inception"; string& p = const_cast <string&> (s); string* ps = const_cast <string*> (&s); // &s 的類型是 const string*dynamic_cast
用 reinterpret_cast 可以將多態基類(包含虛函數的基類)的指針強制轉換為派生類的指針,但是這種轉換不檢查安全性,即不檢查轉換后的指針是否確實指向一個派生類對象。dynamic_cast專門用于將多態基類的指針或引用強制轉換為派生類的指針或引用,而且能夠檢查轉換的安全性。對于不安全的指針轉換,轉換結果返回 NULL 指針。
dynamic_cast 是通過“運行時類型檢查”來保證安全性的。dynamic_cast 不能用于將非多態基類的指針或引用強制轉換為派生類的指針或引用——這種轉換沒法保證安全性,只好用 reinterpret_cast 來完成。
dynamic_cast 示例程序如下:
#include <iostream> #include <string> using namespace std; class Base { //有虛函數,因此是多態基類 public:virtual ~Base() {} }; class Derived : public Base { }; int main() {Base b;Derived d;Derived* pd;pd = reinterpret_cast <Derived*> (&b);if (pd == NULL)//此處pd不會為 NULL。reinterpret_cast不檢查安全性,總是進行轉換cout << "unsafe reinterpret_cast" << endl; //不會執行pd = dynamic_cast <Derived*> (&b);if (pd == NULL) //結果會是NULL,因為 &b 不指向派生類對象,此轉換不安全cout << "unsafe dynamic_cast1" << endl; //會執行pd = dynamic_cast <Derived*> (&d); //安全的轉換if (pd == NULL) //此處 pd 不會為 NULLcout << "unsafe dynamic_cast2" << endl; //不會執行return 0; }程序的輸出結果是:
unsafe dynamic_cast1如果上面的程序中出現了下面的語句:
Derived & r = dynamic_cast <Derived &> (b);那該如何判斷該轉換是否安全呢?不存在空引用,因此不能通過返回值來判斷轉換是否安全。C++ 的解決辦法是:dynamic_cast 在進行引用的強制轉換時,如果發現轉換不安全,就會拋出一個異常,通過處理異常,就能發現不安全的轉換。
總結
以上是生活随笔為你收集整理的C++ 强制类型转换运算符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ 多继承
- 下一篇: C/C++ 文件的后缀名