程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++中的類型轉換static_cast、dynamic_cast、const_cast和reinterpret_cast總結

C++中的類型轉換static_cast、dynamic_cast、const_cast和reinterpret_cast總結

編輯:關於C++

C++中的類型轉換static_cast、dynamic_cast、const_cast和reinterpret_cast總結。本站提示廣大學習愛好者:(C++中的類型轉換static_cast、dynamic_cast、const_cast和reinterpret_cast總結)文章只能為提供參考,不一定能成為您想要的結果。以下是C++中的類型轉換static_cast、dynamic_cast、const_cast和reinterpret_cast總結正文


媒介

這篇文章總結的是C++中的類型轉換,這些小的常識點,有的時刻,本身不是很留意,然則在現實開辟中確切常常應用的。俗語說的好,不懂本身寫的代碼的法式員,不是好的法式員;假如一個法式員關於本身寫的代碼都不懂,只是曉得一昧的的去應用,終有一天,你會迷掉你本身的。

C++中的類型轉換分為兩種:

1.隱式類型轉換;
2.顯式類型轉換。

而關於隱式變換,就是尺度的轉換,在許多時刻,不經意間就產生了,好比int類型和float類型相加時,int類型就會被隱式的轉換位float類型,然後再停止相加運算。而關於隱式轉換不是明天總結的重點,重點是顯式轉換。在尺度C++中有四個類型轉換符:static_cast、dynamic_cast、const_cast和reinterpret_cast;上面將對它們逐個的停止總結。

static_cast

static_cast的轉換格局:static_cast <type-id> (expression)

將expression轉換為type-id類型,重要用於非多態類型之間的轉換,不供給運轉時的檢討來確保轉換的平安性。重要在以下幾種場所中應用:

1.用於類條理構造中,基類和子類之間指針和援用的轉換;
當停止下行轉換,也就是把子類的指針或援用轉換成父類表現,這類轉換是平安的;
當停止下行轉換,也就是把父類的指針或援用轉換成子類表現,這類轉換是不平安的,也須要法式員來包管;

2.用於根本數據類型之間的轉換,如把int轉換成char,把int轉換成enum等等,這類轉換的平安性須要法式員來包管;

3.把void指針轉換成目的類型的指針,是及其不平安的;

注:static_cast不克不及轉換失落expression的const、volatile和__unaligned屬性。

dynamic_cast

dynamic_cast的轉換格局:dynamic_cast <type-id> (expression)

將expression轉換為type-id類型,type-id必需是類的指針、類的援用或許是void *;假如type-id是指針類型,那末expression也必需是一個指針;假如type-id是一個援用,那末expression也必需是一個援用。

dynamic_cast重要用於類條理間的下行轉換和下行轉換,還可以用於類之間的穿插轉換。在類條理間停止下行轉換時,dynamic_cast和static_cast的後果是一樣的;在停止下行轉換時,dynamic_cast具有類型檢討的功效,比static_cast更平安。在多態類型之間的轉換重要應用dynamic_cast,由於類型供給了運轉時信息。上面我將分離在以下的幾種場所下停止dynamic_cast的應用總結:

1.最簡略的下行轉換

好比B繼續自A,B轉換為A,停止下行轉換時,是平安的,以下:

#include <iostream>
using namespace std;
class A
{
     // ......
};
class B : public A
{
     // ......
};
int main()
{
     B *pB = new B;
     A *pA = dynamic_cast<A *>(pB); // Safe and will succeed
}

2.多重繼續之間的下行轉換

C繼續自B,B繼續自A,這類多重繼續的關系;然則,關系很明白,應用dynamic_cast停止轉換時,也是很簡略的:


class A
{
     // ......
};
class B : public A
{
     // ......
};
class C : public B
{
     // ......
};
int main()
{
     C *pC = new C;
     B *pB = dynamic_cast<B *>(pC); // OK
     A *pA = dynamic_cast<A *>(pC); // OK
}

而上述的轉換,static_cast和dynamic_cast具有異樣的後果。而這類下行轉換,也被稱為隱式轉換;好比我們在界說變量時常常這麼寫:B *pB = new C;這和下面是一個事理的,只是多加了一個dynamic_cast轉換符罷了。

3.轉換成void *

可以將類轉換成void *,例如:


class A
{
public:
     virtual void f(){}
     // ......
};
class B
{
public:
     virtual void f(){}
     // ......
};
int main()
{
     A *pA = new A;
     B *pB = new B;
     void *pV = dynamic_cast<void *>(pA); // pV points to an object of A
     pV = dynamic_cast<void *>(pB); // pV points to an object of B
}

然則,在類A和類B中必需包括虛函數,為何呢?由於類中存在虛函數,就解釋它有想讓基類指針或援用指向派生類對象的情形,此時轉換才成心義;因為運轉時類型檢討須要運轉時類型信息,而這個信息存儲在類的虛函數表中,只要界說了虛函數的類才有虛函數表。

4.假如expression是type-id的基類,應用dynamic_cast停止轉換時,在運轉時就會檢討expression能否真實的指向一個type-id類型的對象,假如是,則能停止准確的轉換,取得對應的值;不然前往NULL,假如是援用,則在運轉時就會拋出異常;例如:


class B
{
     virtual void f(){};
};
class D : public B
{
     virtual void f(){};
};
void main()
{
     B* pb = new D;   // unclear but ok
     B* pb2 = new B;
     D* pd = dynamic_cast<D*>(pb);   // ok: pb actually points to a D
     D* pd2 = dynamic_cast<D*>(pb2);   // pb2 points to a B not a D, now pd2 is NULL
}

這個就是下行轉換,從基類指針轉換到派生類指針。
關於一些龐雜的繼續關系來講,應用dynamic_cast停止轉換是存在一些圈套的;好比,有以下的一個構造:

D類型可以平安的轉換成B和C類型,然則D類型如果直接轉換成A類型呢?


class A
{
     virtual void Func() = 0;
};
class B : public A
{
     void Func(){};
};
class C : public A
{
     void Func(){};
};
class D : public B, public C
{
     void Func(){}
};
int main()
{
     D *pD = new D;
     A *pA = dynamic_cast<A *>(pD); // You will get a pA which is NULL
}

假如停止下面的直接轉,你將會獲得一個NULL的pA指針;這是由於,B和C都繼續了A,而且都完成了虛函數Func,招致在停止轉換時,沒法停止決定應當向哪一個A停止轉換。准確的做法是:

int main()
{
     D *pD = new D;
     B *pB = dynamic_cast<B *>(pD);
     A *pA = dynamic_cast<A *>(pB);
}

這就是我在完成QueryInterface時,獲得IUnknown的指針時,應用的是*ppv = static_cast<IX *>(this);而不是*ppv = static_cast<IUnknown *>(this);

關於多重繼續的情形,從派生類往父類的父類停止轉時,須要特殊留意;好比有上面這類情形:

如今,你具有一個A類型的指針,它指向E實例,若何取得B類型的指針,指向E實例呢?假如直接停止轉的話,就會湧現編譯器湧現不合,不曉得是走E->C->B,照樣走E->D->B。關於這類情形,我們就必需先將A類型的指針停止下行轉換,取得E類型的指針,然後,在指定一條准確的道路停止下行轉換。

下面就是關於dynamic_cast轉換的一些細節常識點,特殊是關於多重繼續的情形,在現實項目中,很輕易湧現成績。

const_cast

const_cast的轉換格局:const_cast <type-id> (expression)

const_cast用來將類型的const、volatile和__unaligned屬性移除。常量指針被轉換成異常量指針,而且依然指向本來的對象;常量援用被轉換成異常量援用,而且依然援用本來的對象。看以下的代碼例子:

/*
** FileName     : ConstCastDemo
** Author       : Jelly Young
** Date         : 2013/12/27
** Description  : More information, please go to http://www.jb51.net
*/
#include <iostream>
using namespace std;
class CA
{
public:
     CA():m_iA(10){}
     int m_iA;
};
int main()
{
     const CA *pA = new CA;
     // pA->m_iA = 100; // Error
     CA *pB = const_cast<CA *>(pA);
     pB->m_iA = 100;
     // Now the pA and the pB points to the same object
     cout<<pA->m_iA<<endl;
     cout<<pB->m_iA<<endl;
     const CA &a = *pA;
     // a.m_iA = 200; // Error
     CA &b = const_cast<CA &>(a);
     pB->m_iA = 200;
     // Now the a and the b reference to the same object
     cout<<b.m_iA<<endl;
     cout<<a.m_iA<<endl;
}

注:你不克不及直接對非指針和非援用的變量應用const_cast操作符去直接移除它的const、volatile和__unaligned屬性。

reinterpret_cast

reinterpret_cast的轉換格局:reinterpret_cast <type-id> (expression)

許可將任何指針類型轉換為其它的指針類型;聽起來很壯大,然則也很不靠譜。它重要用於將一種數據類型從一品種型轉換為另外一品種型。它可以將一個指針轉換成一個整數,也能夠將一個整數轉換成一個指針,在現實開辟中,先把一個指針轉換成一個整數,在把該整數轉換成原類型的指針,還可以獲得本來的指針值;特殊是開拓了體系全局的內存空間,須要在多個運用法式之間應用時,須要彼此同享,傳遞這個內存空間的指針時,便可以將指針轉換成整數值,獲得今後,再將整數值轉換成指針,停止對應的操作。

總結

這篇博文總結了C++中的類型轉換,重點總結了個中的顯式轉換。關於C++支撐的這四種顯式轉換都停止了具體的描寫。假如年夜家有甚麼彌補的,或許我總結的有誤的處所,請年夜家多多指教。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved