- C語言中的類型轉換
- C++強制類型轉換
- 爲什麼需要強制類型轉換
- RTTI
一,C語言中的類型轉換
在C語言中分爲了兩種類型轉換,一種是隱式類型轉換,但是隱式類型轉換是相鄰類型之間纔可以進行隱式類型轉換,比如我們的char可以轉爲int,這兩種都是表示數值的。第二種是強制類型轉換,強制類型轉換需要在前面聲明我們需要轉換的。比如將int類型轉換爲int*
#include <iostream>
using namespace std;
int main() {
int a = 10;
char b = 5;
a = b;//隱式類型轉換
cout << a << endl;
//強制類型轉換
int* p = (int*)a;
cout << p << endl;
system("pause");
return EXIT_SUCCESS;
}
缺陷:轉換的可視性比較差,所有的轉換形式都是以一種相同形式書寫。難以追蹤錯誤的轉換。
二,C++強制類型轉換
在c++中爲了加強類型轉換的可視性,引入了四種命名的強制類型轉換操作符
- static_cast
static_cast用來非多態類型的轉換(靜態轉換),編譯器隱式執行的任何類型轉換都可以使用static_cast來轉換。但是不能轉換兩個不相關的類型。
#include <iostream>
using namespace std;
int main() {
int a = 10;
char b = 5;
a = static_cast<int>(b);//隱式類型轉換
cout << a << endl;
//強制類型轉換
int* p = static_cast<int*>(a);
cout << p << endl;
system("pause");
return EXIT_SUCCESS;
}
所明顯的是我們的int類型轉換爲int*類型出錯了。
- reinterpret_cast
reinterpret_cast操作符通常爲操作數的位模式提供較低層次的重新解釋,用於將一種類型轉換爲另一種不同的類型。(也就是我們常說的重新解釋,強制類型轉換)
int* p = reinterpret_cast<int*>(a);
cout << p << endl;
將上面的代碼改成reinterpret_cast就能夠成功編譯運行。
- const_cast
const_cast最常用的用途就是刪除變量的const屬性,方便賦值。
#include <iostream>
using namespace std;
int main() {
const int a = 10;
int& b = const_cast<int&>(a);
b = 20;
cout << a << endl;
cout << b << endl;
system("pause");
return EXIT_SUCCESS;
}
這裏我們常用的就是類型的指針或者引用,將我們的a的值重新定義到b,並且消除const常量。當我們修改b的時候a的值也會被修改。執行程序
a的值並沒有修改。
注意:const常量在使用的時候值是存放在寄存器中,每次使用的時候從寄存器中拿出,並不會從內存中取值。當修改爲20的時候都是內存中的值已經被修改了。使用關鍵字volatile。可以保證每次都是從內存中取值。
volatile const int a = 10;
volatile int& b = const_cast<int&>(a);
修改這兩行代碼。
- dynamic_cast
dynamic_cast用於將一個父類對象的指針轉換爲子類對象的指針或者引用(動態轉換)
向上類型轉換:子類對象指針/引用->父類對象指針/引用,此時不需要轉換,賦值兼容規則
向下類型轉換:父類對象指針/引用轉換爲子類對象的指針或者引用(只有使用dynamic_cast是安全的)。
注意:
1. dynamic_cast只能用於含有虛函數的類
2. dynamic_cast會先價差是否能夠轉型成功,不能返回0;
#include <iostream>
using namespace std;
class A{
public:
virtual void f(){};
};
class B :public A{
};
void fun(A* pa) {
// dynamic_cast會先檢查是否能轉換成功,能成功則轉換,不能則返回
B* pb1 = static_cast<B*>(pa);
B* pb2 = dynamic_cast<B*>(pa);
cout<<"pb1:" <<pb1<< endl;
cout<<"pb2:" <<pb2<< endl;
}
int main() {
A a;
B b;
fun(&a);
fun(&b);
system("pause");
return 0;
}
- explicit
explicit關鍵字阻止經過轉換構造函數進行的隱式轉換的發生
#include <iostream>
using namespace std;
class A{
public:
explicit A(int a){
cout << "A(int a)" << endl;
}
A(const A&a){
cout << "A(const A& a)" << endl;
}
private:
int _a;
};
int main() {
A a1(1);
A a2 = 1;//此時此就不可行了。直接報錯
system("pause");
return 0;
}
三,爲什麼需要四種類型轉換
其實原因很簡單。就是爲了解決在c語言中遺留下來的問題。
- 隱式轉換有些情況可能會出現問題
int main() {
int a = 10;
size_t b = 0;
while (a >= b){
cout << a << endl;
a--;
}
system("pause");
return 0;
}
這種情況就會將a隱式轉換成size_t類型造成死循環。
- 顯示類型轉換將所有情況混合在一起,代碼不清晰,也就是可讀性非常差。
四,RTTI
RTTI就是運行時類型識別
C++通過以下方式支持RTTI
- typeid運算符
- dynamic_cast運算符