類型轉換

1、簡介

類型轉換的含義是經過改變一個變量的類型爲別的類型從而改變該變量的表示方式。程序員

2、C++強制類型轉換

C風格的強制轉換不安全。express

C++強制類型轉換:安全

  • 在C++語言中新增了四個關鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個關鍵字都是用於強制類型轉換的。
  • 新類型的強制轉換能夠提供更好的控制強制轉換過程,容許控制各類不一樣種類的強制轉換。
  • C++中風格是static_cast (content)。C++風格的強制轉換其餘的好處是,它們能更清晰的代表它們要幹什麼。程序員只要掃一眼這樣的代碼,就能當即知道一個強制轉換的目的。

3、具體介紹

一、static_cast:通常的轉換,用於數據類型的強制轉換,強制將一種數據類型轉換爲另外一種數據類型。函數

int a = 98;
	char c = static_cast<char>(a);
	cout << c << endl;// b

基礎數據類型指針,對象指針不可轉換。測試

//基礎數據類型指針
	int* p = NULL;
	char* sp = static_cast<char*>(p);//無效

	//對象指針
	Building* building = NULL;
	Animal* ani = static_cast<Animal*>(building);//無效

能夠轉換具備繼承關係的指針或者引用ui

//父類指針轉成子類指針
	Animal* ani = NULL;
	Cat* cat = static_cast<Cat*>(ani);
	//子類指針轉成父類指針
	Cat* soncat = NULL;
	Animal* anifather = static_cast<Animal*>(soncat);

	//還有具備繼承關係的指針或者引用
	Animal aniobj;
	Animal& aniref = aniobj;
	Cat& cat = static_cast<Cat&>(aniref);

	Cat catobj;
	Cat& catref = catobj;
	Animal& anifather2 = static_cast<Animal&>(catref);

二、dynamic_cast<type_id> (expression), 轉換具備繼承關係的指針或者引用,在轉換前會進行對象類型檢查,而且
只能由子類型轉成基類型極可能失敗。指針

  1. 其餘三種都是編譯時完成的,dynamic_cast是運行時處理的,運行時要進行類型檢查。code

  2. 不能用於內置的基本數據類型的強制轉換對象

    int a = 10;
    char c = dynamic_cast<char>(a);//無效
  3. dynamic_cast轉換若是成功的話返回的是指向類的指針或引用,轉換失敗的話則會返回NULL。繼承

  4. 使用dynamic_cast進行轉換的,基類中必定要有虛函數,不然編譯不經過。

    B中須要檢測有虛函數的緣由:類中存在虛函數,就說明它有想要讓基類指針或引用指向派生類對象的狀況,此時轉換纔有意義。這是因爲運行時類型檢查須要運行時類型信息,而這個信息存儲在類的虛函數表中,只有定義了虛函數的類纔有虛函數表。

  5. 在類的轉換時,在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是同樣的。在進行下行轉換時,dynamic_cast具備類型檢查的功能,比static_cast更安全。

    ​ 向上轉換,即爲子類指針指向父類指針(通常不會出問題),內存大轉小;向下轉換,即將父類指針轉化子類指針,不安全。 向下轉換的成功與否還與將要轉換的類型有關,即要轉換的指針指向的對象的實際類型與轉換之後的對象類型必定要相同,不然轉換失敗。

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

//非繼承關係的指針
	Animal* ani = NULL;
	Building* building = dynamic_cast<Building*>(ani);//報錯
	//具備繼承關係指針
	Animal* ani = NULL;
	Cat* cat = dynamic_cast<Cat*>(ani);//報錯  緣由在於 dynamic作類型安全檢查

	Cat* cat = NULL;
	Animal* ani = dynamic_cast<Animal*>(cat);

三、 const_cast:const限定符一般被用來限定變量,用於表示該變量的值不能被修改,而const_cast則正是用於強制去掉這種不能被修改的常數特性,但須要特別注意的是const_cast不是用於去除變量的常量性,而是去除指向常數對象的指針或引用的常量性,其去除常量性的對象必須爲指針或引用。

  1. 常量指針被強轉爲很是量指針,且仍然指向原來的對象;
  2. 常量引用被強轉爲很是量引用,且仍然指向原來的對象;
  3. 常量對象被強轉爲很是量對象。
//基礎數據類型
	int a = 10;
	const int& b = a;	//b = 10;
	int& c = const_cast<int&>(b);
	c = 20;
	cout << "a:" << a << endl;//20
	cout << "b:" << b << endl;//20
	cout << "c:" << c << endl;//20

	const int a = 10;
	const int& pp = a;
	int& cc = const_cast<int&>(pp);
	cc = 100;
	

	//指針   增長或者去除變量的const性
	const int* p = NULL;
	int* p2 = const_cast<int*>(p);

	int* p3 = NULL;
	const int* p4 = const_cast<const int*>(p3);

四、reinterpret_cast 用法:reinterpret_cast<type_id> (expression)

reinterpret_cast主要有三種強制轉換用途:

  1. 改變指針或引用的類型、
  2. 將指針或引用轉換爲一個足夠長度的整形、
  3. 將整型轉換爲指針或引用類型。

type-id必須是一個指針、引用、算術類型、函數指針或者成員指針。

它能夠把一個指針轉換成一個整數,也能夠把一個整數轉換成一個指針(先把一個指針轉換成一個整數,在把該整數轉換成原類型的指針,還能夠獲得原先的指針值)。

在使用reinterpret_cast強制轉換過程僅僅只是比特位的拷貝,所以在使用過程當中須要特別謹慎!

//1. 無關的指針類型均可以進行轉換
	Building* building = NULL;
	Animal* ani = reinterpret_cast<Animal*>(building);

	//2. 函數指針轉換
	FUNC1 func1;
	FUNC2 func2 = reinterpret_cast<FUNC2>(func1);

4、結論

  • 必須清楚地知道轉變的變量,轉變前是什麼類型,轉換後是什麼類型,以及轉換後有什麼後果。
  • 通常狀況下,不建議使用類型轉換,避免進行類型轉換。
相關文章
相關標籤/搜索