日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 强制类型转换(转载)

發(fā)布時間:2025/3/21 c/c++ 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 强制类型转换(转载) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)載自:http://www.weixueyuan.net/view/6329.html

在C++語言中新增了四個關(guān)鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個關(guān)鍵字都是用于強制類型轉(zhuǎn)換的。我們逐一來介紹這四個關(guān)鍵字。

1) static_cast

在C++語言中static_cast用于數(shù)據(jù)類型的強制轉(zhuǎn)換,強制將一種數(shù)據(jù)類型轉(zhuǎn)換為另一種數(shù)據(jù)類型。例如將整型數(shù)據(jù)轉(zhuǎn)換為浮點型數(shù)據(jù)。

[例1]C語言所采用的類型轉(zhuǎn)換方式:

int a = 10; int b = 3; double result = (double)a / (double)b;

例1中將整型變量a和b轉(zhuǎn)換為雙精度浮點型,然后相除。在C++語言中,我們可以采用static_cast關(guān)鍵字來進行強制類型轉(zhuǎn)換,如下所示。

[例2]static_cast關(guān)鍵字的使用:

int a = 10; int b = 3; double result = static_cast<double>(a) / static_cast<double>(b);

在本例中同樣是將整型變量a轉(zhuǎn)換為雙精度浮點型。采用static_cast進行強制數(shù)據(jù)類型轉(zhuǎn)換時,將想要轉(zhuǎn)換成的數(shù)據(jù)類型放到尖括號中,將待轉(zhuǎn)換的變量或表達式放在元括號中,其格式可以概括為如下形式:
? ? static_cast <類型說明符> (變量或表達式)

2) const_cast

在C語言中,const限定符通常被用來限定變量,用于表示該變量的值不能被修改。而const_cast則正是用于強制去掉這種不能被修改的常數(shù)特性,但需要特別注意的是const_cast不是用于去除變量的常量性,而是去除指向常數(shù)對象的指針或引用的常量性,其去除常量性的對象必須為指針或引用。

[例3]一個錯誤的例子:

const int a = 10; const int * p = &a; *p = 20; //compile error int b = const_cast<int>(a); //compile error

在本例中出現(xiàn)了兩個編譯錯誤,第一個編譯錯誤是*p因為具有常量性,其值是不能被修改的;另一處錯誤是const_cast強制轉(zhuǎn)換對象必須為指針或引用,而例3中為一個變量,這是不允許的!

[例4]const_cast關(guān)鍵字的使用

#include<iostream> using namespace std;int main() {const int a = 10;const int * p = &a;int *q;q = const_cast<int *>(p);*q = 20; //finecout <<a<<" "<<*p<<" "<<*q<<endl;cout <<&a<<" "<<p<<" "<<q<<endl;return 0; }

在本例中,我們將變量a聲明為常量變量,同時聲明了一個const指針指向該變量(此時如果聲明一個普通指針指向該常量變量的話是不允許的,Visual Studio 2010編譯器會報錯),之后我們定義了一個普通的指針*q。將p指針通過const_cast去掉其常量性,并賦給q指針。之后我再修改q指針所指地址的值時,這是不會有問題的。

最后將結(jié)果打印出來,運行結(jié)果如下:
10 20 20
002CFAF4 002CFAF4 002CFAF4

查看運行結(jié)果,問題來了,指針p和指針q都是指向a變量的,指向地址相同,而且經(jīng)過調(diào)試發(fā)現(xiàn)002CFAF4地址內(nèi)的值確實由10被修改成了20,這是怎么一回事呢?為什么a的值打印出來還是10呢?

其實這是一件好事,我們要慶幸a變量最終的值沒有變成20!變量a一開始就被聲明為一個常量變量,不管后面的程序怎么處理,它就是一個常量,就是不會變化的。試想一下如果這個變量a最終變成了20會有什么后果呢?對于這些簡短的程序而言,如果最后a變成了20,我們會一眼看出是q指針修改了,但是一旦一個項目工程非常龐大的時候,在程序某個地方出現(xiàn)了一個q這樣的指針,它可以修改常量a,這是一件很可怕的事情的,可以說是一個程序的漏洞,畢竟將變量a聲明為常量就是不希望修改它,如果后面能修改,這就太恐怖了。

在例4中我們稱“*q=20”語句為未定義行為語句,所謂的未定義行為是指在標準的C++規(guī)范中并沒有明確規(guī)定這種語句的具體行為,該語句的具體行為由編譯器來自行決定如何處理。對于這種未定義行為的語句我們應(yīng)該盡量予以避免!

從例4中我們可以看出我們是不想修改變量a的值的,既然如此,定義一個const_cast關(guān)鍵字強制去掉指針的常量性到底有什么用呢?我們接著來看下面的例子。

例5:

#include<iostream> using namespace std;const int * Search(const int * a, int n, int val);int main() {int a[10] = {0,1,2,3,4,5,6,7,8,9};int val = 5;int *p;p = const_cast<int *>(Search(a, 10, val));if(p == NULL)cout<<"Not found the val in array a"<<endl;elsecout<<"hvae found the val in array a and the val = "<<*p<<endl;return 0; }const int * Search(const int * a, int n, int val) {int i;for(i=0; i<n; i++){if(a[i] == val)return &a[i];}return NULL; }

在例5中我們定義了一個函數(shù),用于在a數(shù)組中尋找val值,如果找到了就返回該值的地址,如果沒有找到則返回NULL。函數(shù)Search返回值是const指針,當我們在a數(shù)組中找到了val值的時候,我們會返回val的地址,最關(guān)鍵的是a數(shù)組在main函數(shù)中并不是const,因此即使我們?nèi)サ舴祷刂档某A啃杂锌赡軙斐蒩數(shù)組被修改,但是這也依然是安全的。

對于引用,我們同樣能使用const_cast來強制去掉常量性,如例6所示。

例6:

#include<iostream> using namespace std;const int & Search(const int * a, int n, int val);int main() { int a[10] = {0,1,2,3,4,5,6,7,8,9}; int val = 5; int &p = const_cast<int &>(Search(a, 10, val)); if(p == NULL) cout<<"Not found the val in array a"<<endl; else cout<<"hvae found the val in array a and the val = "<<p<<endl; return 0; }const int & Search(const int * a, int n, int val) { int i; for(i=0; i<n; i++) { if(a[i] == val) return a[i]; } return NULL; }

了解了const_cast的使用場景后,可以知道使用const_cast通常是一種無奈之舉,同時也建議大家在今后的C++程序設(shè)計過程中一定不要利用const_cast去掉指針或引用的常量性并且去修改原始變量的數(shù)值,這是一種非常不好的行為。

3) reinterpret_cast

在C++語言中,reinterpret_cast主要有三種強制轉(zhuǎn)換用途:改變指針或引用的類型、將指針或引用轉(zhuǎn)換為一個足夠長度的整形、將整型轉(zhuǎn)換為指針或引用類型。在使用reinterpret_cast強制轉(zhuǎn)換過程僅僅只是比特位的拷貝,因此在使用過程中需要特別謹慎!

例7

int *a = new int; double *d = reinterpret_cast<double *>(a); 在例7中,將整型指針通過reinterpret_cast強制轉(zhuǎn)換成了雙精度浮點型指針。
reinterpret_cast可以將指針或引用轉(zhuǎn)換為一個足夠長度的整形,此中的足夠長度具體長度需要多少則取決于操作系統(tǒng),如果是32位的操作系統(tǒng),就需要4個字節(jié)及以上的整型,如果是64位的操作系統(tǒng)則需要8個字節(jié)及以上的整型。???

4) dynamic_cast

dynamic_cast用于類的繼承層次之間的強制類型轉(zhuǎn)換,我們將在講到類的繼承的時候再來介紹dynamic_cast。 轉(zhuǎn)載自:http://www.weixueyuan.net/view/6377.html

在C++中,編譯期的類型轉(zhuǎn)換有可能會在運行時出現(xiàn)錯誤,特別是涉及到類對象的指針或引用操作時,更容易產(chǎn)生錯誤。Dynamic_cast操作符則可以在運行期對可能產(chǎn)生問題的類型轉(zhuǎn)換進行測試。

#include<iostream> using namespace std;class base { public :void m(){cout<<"m"<<endl;} };class derived : public base { public:void f(){cout<<"f"<<endl;} };int main() {derived * p;p = new base;p = static_cast<derived *>(new base);p->m();p->f();return 0; }

本例中定義了兩個類:base類和derived類,這兩個類構(gòu)成繼承關(guān)系。在base類中定義了m函數(shù),derived類中定義了f函數(shù)。在前面介紹多態(tài)時,我們一直是用基類指針指向派生類或基類對象,而本例則不同了。本例主函數(shù)中定義的是一個派生類指針,當我們將其指向一個基類對象時,這是錯誤的,會導(dǎo)致編譯錯誤。但是通過強制類型轉(zhuǎn)換我們可以將派生類指針指向一個基類對象,p = static_cast<derived *>(new base);語句實現(xiàn)的就是這樣一個功能,這樣的一種強制類型轉(zhuǎn)換時合乎C++語法規(guī)定的,但是是非常不明智的,它會帶來一定的危險。在程序中p是一個派生類對象,我們將其強制指向一個基類對象,首先通過p指針調(diào)用m函數(shù),因為基類中包含有m函數(shù),這一句沒有問題,之后通過p指針調(diào)用f函數(shù)。一般來講,因為p指針是一個派生類類型的指針,而派生類中擁有f函數(shù),因此p->f();這一語句不會有問題,但是本例中p指針指向的確實基類的對象,而基類中并沒有聲明f函數(shù),雖然p->f();這一語句雖然仍沒有語法錯誤,但是它卻產(chǎn)生了一個運行時的錯誤。換言之,p指針是派生類指針,這表明程序設(shè)計人員可以通過p指針調(diào)用派生類的成員函數(shù)f,但是在實際的程序設(shè)計過程中卻誤將p指針指向了一個基類對象,這就導(dǎo)致了一個運行期錯誤。


產(chǎn)生這種運行期的錯誤原因在于static_cast強制類型轉(zhuǎn)換時并不具有保證類型安全的功能,而C++提供的dynamic_cast卻能解決這一問題,dynamic_cast可以在程序運行時檢測類型轉(zhuǎn)換是否類型安全。當然dynamic_cast使用起來也是有條件的,它要求所轉(zhuǎn)換的操作數(shù)必須包含多態(tài)類類型(即至少包含一個虛函數(shù)的類)。

例2:

#include<iostream> using namespace std;class base { public :void m(){cout<<"m"<<endl;} };class derived : public base { public:void f(){cout<<"f"<<endl;} };int main() {derived * p;p = new base;p = dynamic_cast<derived *>(new base);p->m();p->f();return 0; }

在本例中利用dynamic_cast進行強制類型轉(zhuǎn)換,但是因為base類中并不存在虛函數(shù),因此p = dynamic_cast<derived *>(new base);這一句會編譯錯誤。dynamic_cast能否正確轉(zhuǎn)換與目標類型是否為多態(tài)類類型無關(guān),dynamic_cast要求被轉(zhuǎn)換的類型必須為多態(tài)類類型。為了解決本例中的語法錯誤,我們可以將base類中的函數(shù)m聲明為虛函數(shù),virtual void m(){cout<<"m"<<endl;}。

dynamic_cast還要求<>內(nèi)部所描述的目標類型必須為指針或引用。如例3所示,如果我們將例2中的主函數(shù)換成例3的形式,這也是無法通過編譯的。

例3:

int main() {base b;dynamic_cast<derived>(b);return 0; }

我們來看一下正確使用dynamic_cast的代碼。

例4:

#include<iostream> using namespace std;class base { public :virtual void m(){cout<<"m"<<endl;} };class derived : public base { public:void f(){cout<<"f"<<endl;} };int main() {derived * p;p = dynamic_cast<derived *>(new base);if(p){p->m();p->f(); }elsecout<<"Convert not safe!"<<endl;return 0; }

在本例中通過dynamic_cast來初始化指針p,在初始化過程中dynamic_cast會檢測操作數(shù)new base轉(zhuǎn)換為目標類型derived *是否能保證類型安全,如果類型安全則將new base結(jié)果賦給p指針,否則返回0,也即false。而本例中是要用基類對象地址去初始化派生類指針,這顯然是無法保證類型安全的,因此p最后得到的返回值是0。在主函數(shù)中經(jīng)過判斷語句,最終程序輸出“Convert not safe!”。

Dynamic_cast轉(zhuǎn)換有自己的規(guī)則,下面將通過示例來介紹轉(zhuǎn)換規(guī)則。

例4:

#include<iostream> using namespace std;class base { public :virtual void m(){cout<<"m"<<endl;} };class derived : public base { public:virtual void f(){cout<<"f"<<endl;} };int main() {derived * d;d = dynamic_cast<derived *>(new base);if(d){cout<<"Base to Derived is ok"<<endl;delete d;}elsecout<<"Base to Derived is error"<<endl;base * b;b = dynamic_cast<base *>(new derived);if(b){cout<<"Derived to Base is ok"<<endl;delete b;}elsecout<<"Derived to Base is error"<<endl;return 0; }

本例分別定義了兩個類:base類和derived類,這兩個類構(gòu)成繼承關(guān)系,為了測試dynamic_cast轉(zhuǎn)換規(guī)則,我們在類中各自定義了一個虛函數(shù)。在本例的主函數(shù)中我們分別測試基類轉(zhuǎn)換為派生類和派生類轉(zhuǎn)換為基類時dynamic_cast轉(zhuǎn)換返回值。本例最終運行結(jié)果如下:
??? Base to Derived is error
??? Derived to Base is ok

從結(jié)果可以看出從不能將指向基類對象的指針轉(zhuǎn)換為指向派生類對象的指針,但是可以將指向派生類對象的指針轉(zhuǎn)換為指向基類對象的指針。

例5:

#include<iostream> using namespace std;class A { public :virtual void m(){cout<<"m"<<endl;} };class B { public:virtual void f(){cout<<"f"<<endl;} };int main() {A * a;a = dynamic_cast<A *>(new B);if(a){cout<<"B to A is ok"<<endl;delete a;}elsecout<<"B to A is error"<<endl;B * b;b = dynamic_cast<B *>(new A);if(b){cout<<"A to B is ok"<<endl;delete b;}elsecout<<"A to B is error"<<endl;return 0; } 在本例中,定義了兩個類A和B,這兩個類不構(gòu)成繼承關(guān)系,我們嘗試將指向兩個類對象的指針進行互相轉(zhuǎn)換,看程序運行結(jié)果:
??? B to A is error
??? A to B is error

從程序運行結(jié)果不難看出,任意兩個不相關(guān)的多態(tài)類類型之間的轉(zhuǎn)換也是不能進行的。

總結(jié)一下dynamic_cast轉(zhuǎn)換規(guī)則,只允許指向派生類對象的指針轉(zhuǎn)換為指向基類對象的指針。

C++提供的兩個類型轉(zhuǎn)換操作符static_cast和dynamic_cast,static_cast可以用于任何類型的強制類型轉(zhuǎn)換,但是它不保證轉(zhuǎn)換過程中的類型安全,dynamic_cast只能用于多態(tài)類類型的轉(zhuǎn)換,而且要求轉(zhuǎn)換的目的類型必須為指針或引用,并且它可以保證轉(zhuǎn)換過程中類型安全。

?

轉(zhuǎn)載于:https://www.cnblogs.com/EggKiller/p/5817893.html

總結(jié)

以上是生活随笔為你收集整理的C++ 强制类型转换(转载)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。