基礎類型轉換
- 標準數據類型之間會進行隱式的類型安全轉換
-
轉換規則如下:
(char -> short)-> int -> unsigned int -> long -> unsigned long -> float -> double
舉個例子:
#include <iostream>
#include <string>
using namespace std;
int main()
{
short s = 'a';
unsigned int ui = 1000;
int i = -2000;
double d = i;
//把int類型的i轉換成double類型,但都是有符號的
//輸出-2000
cout << "d = " << d << endl;
//輸出1000,不涉及類型轉換
cout << "ui = " << ui << endl;
//把有符號的int類型轉換成無符號的int,
//再進行相加
//輸出4294966296
cout << "ui + i = " << ui + i << endl;
//unsigned int比int類型要大,所以結果必大于0
if( (ui + i) > 0 )
{
cout << "Positive" << endl;
}
else
{
cout << "Negative" << endl;
}
//這里把short 和 char 類型全部轉換為int類型再取大小
//所以這里輸出4
cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl;
return 0;
}
基礎類型轉類類型
首先看一段代碼
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test()
{
mValue = 0;
}
Test(int i)
{
mValue = i;
}
int value()
{
return mValue;
}
};
int main()
{
Test t;
t = 100;
cout << t.value() << endl;
return 0;
}
這段代碼的輸出結果是:
100
有沒有想過為什么呢?
其實這里涉及到一個 轉換構造函數
:
- 轉換構造函數可以定義不同類型的參數
- 轉換構造函數在類型轉換時被調用
- 參數滿足下列條件時成為
轉換構造函數
- 有且僅有一個參數
- 參數是基本類型
- 參數是其它類類型(不是當前類類型)
學習了這個新知識以后,就可以推斷出編譯器的行為了:
- 100這個立即數默認為int類型,不能直接賦值給t對象
- 看看有沒有轉換構造函數
- 發現Test類中定義了Test(int i),可以進行轉換
- 那就把t = 100默認等價為:t = Test(100)
所以最終的結果是編譯器調用了轉換構造函數把int類型的值賦值給成員變量。
注意:
- 編譯器盡力嘗試的結果是隱式類型轉換
- 隱式類型轉換
- 會讓程序以意想不到的方式進行工作
- 是工程中Bug的重要來源
所以這里再學習一個知識點: explicit
關鍵字:
- 工程中通過
explicit
關鍵字杜絕編譯器的轉換嘗試 -
explicit
關鍵字用于杜絕隱式類型轉換 - 轉換構造函數被
explicit
修飾時只能進行顯示轉換- 轉換方式
- static-cast< ClassName > ( value )
- ClassName ( value )
- ( ClassName ) value; //不推薦
- 轉換方式
舉個例子:
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test()
{
mValue = 0;
}
//顯示的修飾轉換構造函數
explicit Test(int i)
{
mValue = i;
}
//重載加號操作符
Test operator + (const Test& p)
{
Test ret(mValue + p.mValue);
return ret;
}
int value()
{
return mValue;
}
};
int main()
{
Test t;
//由于是顯示的修飾轉換構造函數
//所以使用static_cast 來顯示的轉換
// t = Test(5);
t = static_cast<Test>(5);
Test r;
// r = t + Test(10);
r = t + static_cast<Test>(10);
cout << r.value() << endl;
return 0;
}
類類型轉基礎類型
既然可以將一個基礎類型數據轉為類對象,那么可不可以將類對象轉為基礎類型數據呢? 這里我們繼續學一個知識點 類型轉換函數
:
- C++類中可以定義
類型轉換函數
-
類型轉換函數
用于將類對象轉換為其它類型 - 語法規則:
operator Type()
{
Type ret;
// .....
return ret;
}
舉個例子:
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test(int i = 0)
{
mValue = i;
}
int value()
{
return mValue;
}
//定義類型轉換函數
operator int ()
{
return mValue;
}
};
int main()
{
Test t(100);
//將類類型轉為基礎數據類型
int i = t;
cout << "t.value() = " << t.value() << endl;
cout << "i = " << i << endl;
return 0;
}
再來學幾個關于 類型轉換函數
的知識點吧:
- 與
轉換構造函數
具有同等的地位 - 使得編譯器有能力將
對象
轉換為其它類型 - 編譯器能夠隱式的使用
類型轉換函數
類類型之間轉換
學會了 類類型
和 基礎類型
的相互轉換以后,最后學一下 '類類型' 之間的轉換。
其實 類類型
之間的轉換也使用到 類型轉換函數
。如下:
#include <iostream>
#include <string>
using namespace std;
class Test;
class Value
{
public:
Value()
{
}
//因為這里的轉換構造函數會和類型轉換函數沖突
//所以這里直接顯式的聲明不進行隱式轉換
explicit Value(Test& t)
{
}
};
class Test
{
int mValue;
public:
Test(int i = 0)
{
mValue = i;
}
int value()
{
return mValue;
}
//這里使用類型轉換函數
//規定轉為Value類
operator Value()
{
Value ret;
cout << "operator Value()" << endl;
return ret;
}
};
int main()
{
Test t(100);
//這里直接把Test類轉換為Value類
Value v = t;
return 0;
}
注意:
- 無法抑制隱式的類型轉換函數調用
- 類型轉換函數可能與轉換構造函數沖突
- 工程中以 Type toType( ) 的公有成員函數代替類型轉換函數