我們之前在 C 語言進行類型轉換是強制類型轉換的,這樣極易出 bug,還不易查找。格式如下:(Type)(Experssion) 或 Type(Experssion),我們來看個示例代碼,看看 C 語言中的強制類型轉換
#include <stdio.h>
typedef void(PF)(int);
struct Point
{
int x;
int y;
};
int main(int argc, char *argv[])
{
int v = 0x12345;
PF* pf = (PF*)v;
char c = char(v);
Point* p = (Point*)v;
pf(5);
printf("p->x = %d\n", p->x);
printf("p->y = %d\n", p->y);
return 0;
}
編譯結果如下

我們看到直接運作段錯誤,但是它編譯是通過的,是以我們如果在大型的項目中是難以查找 bug 的。
在 C 方式的強制類型轉換的過程中,它存在的問題:a> 過于粗暴:任意類型之間都可以進行轉換,編譯器很難判斷其正确性;b> 難于定位:在源碼中無法快速定位所有使用強制類型轉換的語句。那麼強制類型轉換在實際工程中是很難完全避免的!如何進行更加安全可靠的轉換呢?在 C++ 中出現了新式類型轉換,C++ 将強制類型轉換分為 4 中不同的類型:a> static_cast;b> const_cast;c> dynamic_cast;d> reinterpret_cast;用法是:xxx_cast<Type>(Expression)。下來我們分别來講下這四種新式類型轉換的特點及要求
A、static_cast 強制類型轉換
用于基本類型間的轉換;不能用于基本類型指針間的轉換;用于有繼承關系類對象之間的轉換和類指針之間的轉換。
B、const_cast 強制類型轉換
用于去除變量的隻讀屬性;強制轉換的目标類型必須是指針或引用。
C、reinterpret_cast 強制類型轉換
用于指針類型間的強制轉換;用于整數和指針類型間的強制轉換。
D、dynamic_cast 強制類型轉換
用于有繼承關系的類指針間的轉換;用于有交叉關系的類指針間的轉換;具有類型檢查的功能;需要虛函數的支援。
關于上面講到的有些概念,我們會在後面進行詳細的介紹,下來我們以代碼為例進行分析
#include <stdio.h>
void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int* pi = &i;
char* pc = &c;
c = static_cast<char>(i);
pc = static_cast<char*>(pi); // error
}
void const_cast_demo()
{
const int& j = 1;
int& k = const_cast<int&>(j);
const int x = 2;
int& y = const_cast<int&>(x);
int z = const_cast<int>(x); // error
k = 5;
printf("k = %d\n", k);
printf("j = %d\n", j);
y = 8;
printf("x = %d\n", x);
printf("y = %d\n", y);
printf("&x = %p\n", &x);
printf("&y = %p\n", &y);
}
void reinterpret_cast_demo()
{
int i = 0;
char c = 'c';
int* pi = &i;
char* pc = &c;
pc = reinterpret_cast<char*>(pi);
pi = reinterpret_cast<int*>(pc);
pi = reinterpret_cast<int*>(i);
c = reinterpret_cast<char>(i); // error
}
void dynamic_cast_demo()
{
int i = 0;
int* pi = &i;
char* pc = dynamic_cast<char*>(pi); // error
}
int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo();
return 0;
}
我們來分析下這個代碼,在 static_cast_demo 中,static_cast 不能用于指針間的轉換,是以第 11 行會報錯。在 const_cast_demo 中,第 16 行定義了一個具有隻讀屬性的變量 j,我們還是可以通過 const_cast 來改變它的屬性的。第 19 行定義了一個真正意義上的常量,它會進入到符号表中,但在棧上會為它配置設定 4 個位元組的空間,是以第 20 行的也會成功。const_cast 強制轉換的目标類型必須是指針或引用,是以第 22 行會報錯。第 26 、 27 行會列印出 5、5;第 31 - 34 會列印出 2、8、後面兩個位址是一樣的。在 reinterpret_cast_demo 中,reinterpret_cast 用于指針類型間及整數和指針類型間的強制轉換,是以第 47 行會報錯。在 dynamic_cast_demo 中,第 54 行會報錯。我們來看看編譯結果
我們分别注釋掉這幾行,再來編譯,看看結果是否如我們所分析的那樣