欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++實例講解四種類型轉換的使用

 更新時間:2022年06月13日 14:15:41   作者:你算哪一個bug?  
在C++語言中新增了四個關鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個關鍵字都是用于類型轉換的,類型轉換(type cast),是高級語言的一個基本語法。它被實現(xiàn)為一個特殊的運算符,以小括號內(nèi)加上類型名來表示,接下來讓我們一起來詳細了解

C++類型轉換

C語言風格的轉換

C語言提供了自己的一套轉換規(guī)則,有好處也有壞處。

C語言的風格:(type_name)expression;

C語言提供了隱式類型轉換和顯式類型轉換。顯式類型轉換一般也叫做強轉,隱式類型轉換編譯器完成,如果轉換不了就報錯。

而C語言類型轉換的風格好處就是簡單,缺陷比如轉換的可視性差,顯式類型轉換的寫法就只有一種,難以精準的跟蹤錯誤。

??char ch=1.1,char ch=1在.cpp下都是合法的,這就是隱式類型轉換,C語言下如果把一個結構體給int就會報錯,因為編譯器不知道怎么去轉,C++下可以通過實現(xiàn)operator int()實現(xiàn)類型轉換或者提供合適的構造函數(shù)完成隱式類型轉換,下面以在.cpp中實現(xiàn)operator int()為例

下面這段代碼由于隱式類型轉換導致了死循環(huán)

C語言的類型轉換其實已經(jīng)足夠完成需求了,但是可視性不太好,比如你不能在代碼庫中搜索它(就一對括號怎么去搜索),所以C++提供了一套類型轉換,相當于語法糖了,此外還會進行一些編譯性檢查(比如dynamic_cast轉換失敗則返回空指針)。但其實作用都是一樣的。

C++風格的類型轉換

C++標準為了增加類型轉換的可見性,提供了四種類型轉化的方式。

static_cast

靜態(tài)類型轉換,進行相關類型的轉換,但不能轉換兩個不相關的類型(即編譯器看到這個轉換是行不通的就會報錯)。

static_cast < type-id > ( expression )

int main()
{
	double a = (int)5.5 + 5.3;//結果是10.3
	double b = static_cast <int>(5.5) + 5.3;
	cout << "a: " << a << endl;
	cout << "b: " << b << endl;
	return 0;
}

轉換不相關的類型:

reinterpret_cast

很暴力的一個操作符,由英文直譯過來就是重新解釋的轉型。白話就是將一段內(nèi)存重新解釋。

網(wǎng)上看到很多大佬的理解,這里借用或摻雜自己的思想:static_cast是做類型能做的轉換,不行編譯器就報錯,告訴你這樣是不合理的,reinterpret_cast則是就算不能轉換編譯器你也別報錯,我心里有數(shù)。由于reinterpret_cast本質上是一個編譯器指令,所以實際動作完全取決于編譯器,失去了移植性。

暴力歸暴力,但也是合理范圍內(nèi)的,比如你把一個結構體硬塞給int肯定是不行的,但是把結構體指針重新解釋為int那是一點問題沒有。

此外reinterpret_cast重新解釋的辦法是把那一塊內(nèi)存的比特位全部復制下來重新解釋。

下面的例子把一個結構體指針解釋為int再加上5.3。

struct Test
{
	int a;
};
int main()
{
	Test* t = new Test;
	double c = reinterpret_cast <int>(&t) + 5.3;
	cout << c << endl;
	return 0;
}

const_cast

刪除變量的const屬性,一般和指針或引用連用

int main()
{
	const int a = 1;//a是常變量,在棧上
	int* p = const_cast<int*>(&a);
	*p = 2;
	cout << a << endl;
	cout << *p << endl;
	return 0;
}

volatile const int a=1;//打印的a就會是2

volatile后編譯器對訪問該變量的代碼不再優(yōu)化。比如上面那句代碼打印1就是因為編譯器優(yōu)化,讀取的a是從寄存器中讀取的,而不是內(nèi)存。

多線程中也有很多關于 volatile的應用。

dynamic_cast

dynamic_cast,安全的向下轉型。

多態(tài)的轉換中向下轉型(父類轉為子類)用dynamic是安全的,但是父類必須有虛函數(shù),否則編譯報錯,且只能用于指針或引用。

向上轉型,子類給父類,發(fā)生切割,不需要轉換。

向下轉型,父類地址給子類指針,需要類型轉換,由于是類型是子類指針,但是給的地址是父類的,如果用指針去訪問子類獨有的數(shù)據(jù)可能就會造成越界,然后程序就可能崩了,所以此時就需要dynamic_cast進行轉換了,因為dynamic_cast會檢查父類指針是否指向的是這個子類,如果是父類說明可能帶來一些安全問題,會轉換失敗返回空指針,反之則實現(xiàn)轉換。

理解向下轉型不安全有個例子:男人是人,但人不一定是男人(男人派生自人,男人的指針=(男人類型的指針強轉)人的地址,此時如果通過男人指針去調(diào)用男人自己獨有的特性就是越界,因為實際上拿到的是人的地址,并沒有存儲男人的特性,也可以從空間大小上來解釋,人是父類,空間更小,男人是子類,空間更大,給的是小空間,卻有了訪問大空間的能力,所以可能造成越界,所以是不安全的)

此外在一個父類有多個子類且需要類型轉換時,dynamic_cast也能起到作用,舉個例子

//父類是Entity,子類是Player和Enemy, e,player,enemy分別表示他們對應的實例化對象
Entity* p=&player;
Enemy* p1=(Enemy*)p;//向下轉型需要強轉,這樣搞就出問題了,p明明指向的是一個player,現(xiàn)在類型為Enemy的指針居然指向了一個Player的對象,如果對其內(nèi)存進行了操作,那后果是不可預料的。

父類指針一開始指向一個父類對象,再給到子類類型的指針,存在越界的風險,如果為了保證安全則需要檢查。

父類的指針指向子類對象(向上轉型),再給到子類指針,合理。

所以建議使用dynamic_cast,因為可以保證安全, 轉換失敗返回空指針(NULL)。

dynamic_cast的底層與RTTI有關,借助RTTI拿到類型信息,所以dynamic_cast更像一個函數(shù),因為不是編譯指令,所以會帶來一些性能的損失。

RTTI 是“Runtime Type Information”的縮寫,意思是運行時類型信息。RTTI存儲了所有類型運行時的類型信息,增加了開銷但是可以讓我們做更多的操作。dynamic_cast的底層就是借助了RTTI+匹配,具體的不太了解。VS可以關閉RTTI,但是也就不能用dynamic_cast了

下面給一個代碼例子

class Entity
{
public:
	virtual void Print() {};//dynamic_cast使用的前提必須是父類有虛函數(shù)
};
class Player:public Entity
{
};
class Enemy :public Entity
{
};
void Check(void* p)
{
	if (p)
	{
		cout << "轉換成功" << endl;
	}
	else
	{
		cout << "轉換失敗" << endl;
	}
}
int main()
{
	Entity* e = new Entity();
	Entity* actuallyPlayer = new Player();//向上轉型
	//安全的向下轉型
	Player* player =(Player*)actuallyPlayer;//向下轉型需要轉換類型
	Player* player2 = dynamic_cast<Player*>(actuallyPlayer);
	Check(player2); cout << endl;
	//不安全的向下轉型
	Player* player3 = (Player*)e;
	Player* player4 = dynamic_cast<Player*>(e);
	Check(player4); cout << endl;
	Entity* actuallyEnemy = new Enemy();
	Player* player5 = dynamic_cast<Player*>(actuallyEnemy);
	Check(player5); cout << endl;
	return 0;
}

dynamic也常常利用返回值是否是空指針來判斷指針具體指向誰。

用dynamic_cast的地方其實也可以用static_cast,不過static_cast不會進行安全檢查,如果你很清楚其指向,并且在安全的前提下,為了減少程序開銷那可以考慮用static_cast

小結

  • static_cast用于相關類型的轉換
  • reinterpret_cast用于重新解釋內(nèi)存(很暴力,用的時候心里要有數(shù))
  • const_cast常用來取出const屬性,常與指針連用來修改const變量的值
  • dynamic_cast,在多態(tài)里提供安全的向下轉換(轉換不安全就返回空指針,只要對返回的指針進行判斷我們就能知道此次轉換安不安全了)

到此這篇關于C++實例講解四種類型轉換的使用的文章就介紹到這了,更多相關C++類型轉換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C語言使用rand函數(shù)生成隨機數(shù)

    C語言使用rand函數(shù)生成隨機數(shù)

    這篇文章介紹了C語言使用rand函數(shù)生成隨機數(shù)的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-12-12
  • C語言利用面試真題理解指針的使用

    C語言利用面試真題理解指針的使用

    C語言這門課程在計算機的基礎教學中一直占有比較重要的地位,然而要想突破C語言的學習,對指針的掌握是非常重要的,本文將具體針對指針的基礎做詳盡的介紹
    2022-08-08
  • C++中的運算符和運算符優(yōu)先級總結

    C++中的運算符和運算符優(yōu)先級總結

    這篇文章主要介紹了C++中的運算符和運算符優(yōu)先級總結,主要整理了算術、關系、邏輯、位和賦值運算符的用法,需要的朋友可以參考下
    2016-05-05
  • C語言中數(shù)據(jù)結構之鏈表歸并排序實例代碼

    C語言中數(shù)據(jù)結構之鏈表歸并排序實例代碼

    這篇文章主要介紹了C語言中數(shù)據(jù)結構之鏈表歸并排序實例代碼的相關資料,需要的朋友可以參考下
    2017-05-05
  • Qt學習教程之表格控件螞蟻線詳解

    Qt學習教程之表格控件螞蟻線詳解

    如果有用過PS的選區(qū)工具應該就會知道螞蟻線是什么東西了,就是用來表示選區(qū)的一種虛線,關鍵還是要動態(tài)的!下面這篇文章主要給大家介紹了關于Qt學習教程之表格控件螞蟻線的相關資料,需要的朋友可以參考下
    2018-07-07
  • 枚舉類型的定義和應用總結

    枚舉類型的定義和應用總結

    如果一種變量只有幾種可能的值,可以定義為枚舉類型。所謂“枚舉類型”是將變量的值一一列舉出來,變量的值只能在列舉出來的值的范圍內(nèi)
    2013-10-10
  • 簡要對比C語言中的dup()函數(shù)和dup2()函數(shù)

    簡要對比C語言中的dup()函數(shù)和dup2()函數(shù)

    這篇文章主要介紹了簡要對比C語言中的dup()函數(shù)和dup2()函數(shù),是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-08-08
  • C語言字符串原地壓縮實現(xiàn)方法

    C語言字符串原地壓縮實現(xiàn)方法

    這篇文章主要介紹了C語言字符串原地壓縮實現(xiàn)方法,包含了字符串的遍歷與轉換等操作,是很實用的操作技巧,需要的朋友可以參考下
    2014-09-09
  • C++ 超詳細深入分析單例模式

    C++ 超詳細深入分析單例模式

    單例模式(Singleton Pattern)是最簡單的設計模式之一。這種類型的設計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,這種模式涉及到一個單一的類,該類負責創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建
    2022-03-03
  • C語言實現(xiàn)掃雷游戲詳解(附源碼)

    C語言實現(xiàn)掃雷游戲詳解(附源碼)

    大家好,本篇文章主要講的是C語言實現(xiàn)掃雷游戲詳解(附源碼),感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01

最新評論