一、通常C++中內置類型轉換:
在C++中,將一個標準類型的變量 的 值 賦給 另一種標準類型的 變量時,如果這兩種類型兼容,則C++自動將這個值轉換爲接收變量的類型。如:
long a = 11; //將11從int型轉換爲long類型
double b = 22; //將22從int型轉換爲double型
int c = 33.33; //將33.33從double型轉換爲int型,值變爲33
二、類中的類型準換:
在C++中,僅僅 接受一個參數的 構造函數 被稱爲 類型轉換函數。
若構造函數有多個參數,如果除了第一個參數外 的 其它參數 都有默認值,則 此構造函數 也是 類型轉換函數。
類型轉換函數 能夠實現 參數類型 到 類類型 的自動轉換(強制轉換)。
構造函數用作 自動類型轉換函數 的過程是 隱式轉換。
//這種隱式轉換存在風險,關鍵字explict用於關閉這種自動隱式轉換特性。
類的定義示例:
//stonewt.h -- definition for the Stonewt class
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
enum { Lbs_per_stn = 14 }; // pounds per stone,定義類特定的常量,如果常量是整數,enum方法
//static const int Lbs_per_stn = 14; //或者static方法,或者在構造函數初始化列表中賦值
int stone; // whole stones
double pds_left; // fractional pounds
double pounds; // entire weight in pounds
public:
Stonewt(double lbs); // 有一個double參數的構造函數
Stonewt(int stn, double lbs); // constructor for stone, lbs //沒有顯式聲明explict
Stonewt(); // 默認無參構造函數
~Stonewt(); // 析構函數
void show_lbs() const; //show weight in pounds format
void show_stn() const; //show weight in stone format
};
#endif // !STONEWT_H_
// stonewt.cpp -- Stonewt methods
#include <iostream>
#include "stonewt.h"
using namespace std;
//construct Stonewt object from double value
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn; //integer division
pds_left = int(lbs) % Lbs_per_stn + lbs - int(lbs);
pounds = lbs;
cout << "一個double參數的Stonewt構造函數被調用!" << endl;
}
//construct Stonewt object from stone, double values
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * double(Lbs_per_stn) + lbs;
cout << "一個int參數和一個double參數的Stonewt構造函數被調用!" << endl;
}
//default constructor, wt = 0
Stonewt::Stonewt()
{
stone = 0;
pounds = 0.0;
pds_left = 0.0;
cout << "沒有參數的Stonewt默認構造函數被調用!" << endl;
}
// destructor
Stonewt::~Stonewt()
{
cout << "Stonewt()析構函數被調用" << endl;
}
//show weight in stones
void Stonewt::show_stn() const
{
cout << stone << " stone, " << pds_left << "pounds" << endl;
}
//show weight in pounds
void Stonewt::show_lbs() const
{
cout << pounds << " pounds" << endl;
}
上面的stonewt.h和stonewt.cpp 文件定義了一個類Stonewt,其中有參數是double類型的 類型轉換構造函數Stonewt(double lbs);
編譯器使用Stonewt(double )函數的時機:
- 將Stonewt對象初始化爲double值時。
- 將double值賦給Stonewt對象時。
- 將double值傳遞給接受Stonewt對象的函數時。
- 返回值被聲明爲Stonewt和函數試圖返回double類型的內置類型時。
================================================================
函數原型化提供的參數匹配過程:允許使用Stonewt(double )構造函數來轉換其他數值類型。
Stonewt Jumbo(1000);
Jumbo = 1000;
上面兩條語句都首先將 int類型轉換爲 double類型,然後使用Stonewt(double )構造函數。
注意:當且僅當轉換不存在 二義性時,纔會進行這種 二步轉換。
如果這個類還定義了 構造函數Stonewt(long ),則編譯器將拒絕這些語句,可能指出:int可能被轉換爲long或double,因此調用存在二義性。
三、示例:
//stone.cpp -- user-defined conversions
//compile with stonewt.cpp
#include <iostream>
#include "stonewt.h"
//using namespace std;
using std::cout;
using std::endl;
void display(const Stonewt& st, int n)
{
for (int i = 0; i < n; ++i)
{
cout << "Wow! ";
st.show_stn();
}
}
Stonewt reshow(double d)
{
return d;
}
int main()
{
Stonewt incognito = 275; //uses constructor to initialize
Stonewt wolfe(285.7); //same as Stonewt wolfe = 285.7;
Stonewt taft(21, 8);
cout << "==================<1>=====================" << endl;
cout << "The celebrity weighted ";
incognito.show_stn();
cout << "The detective weighted ";
wolfe.show_stn();
cout << "The president weighted ";
taft.show_lbs();
cout << "==================<2>=====================" << endl;
incognito = 276.8; // uses constructor for conversion
cout << "*****" << endl;
taft = 325; // same as taft = Stonewt(325)
cout << "==================<3>=====================" << endl;
cout << "After dinner, the celebrity weighted ";
incognito.show_lbs();
cout << "After dinner, the President wighted ";
taft.show_lbs();
cout << "==================<4>=====================" << endl;
display(taft, 2);
cout << "The wrestler wighted even more." << endl;
cout << "==================<5>=====================" << endl;
display(422, 2);
cout << "No stone left unearned" << endl;
cout << "==================<6>=====================" << endl;
reshow(11.1);
cout << "==================<7>=====================" << endl;
return 0;
}
運行結果:
一個double參數的Stonewt構造函數被調用!
一個double參數的Stonewt構造函數被調用!
一個int參數和一個double參數的Stonewt構造函數被調用!
==================<1>=====================
The celebrity weighted 19 stone, 9pounds
The detective weighted 20 stone, 5.7pounds
The president weighted 302 pounds
==================<2>=====================
一個double參數的Stonewt構造函數被調用!
Stonewt()析構函數被調用
*****
一個double參數的Stonewt構造函數被調用!
Stonewt()析構函數被調用
==================<3>=====================
After dinner, the celebrity weighted 276.8 pounds
After dinner, the President wighted 325 pounds
==================<4>=====================
Wow! 23 stone, 3pounds
Wow! 23 stone, 3pounds
The wrestler wighted even more.
==================<5>=====================
一個double參數的Stonewt構造函數被調用!
Wow! 30 stone, 2pounds
Wow! 30 stone, 2pounds
Stonewt()析構函數被調用
No stone left unearned
==================<6>=====================
一個double參數的Stonewt構造函數被調用!
Stonewt()析構函數被調用
==================<7>=====================
Stonewt()析構函數被調用
Stonewt()析構函數被調用
Stonewt()析構函數被調用
四、explict
在C++中,explicit關鍵字只能用於修飾只有一個參數的類構造函數,它的作用是表明該構造函數是顯示的,而非隱式的,跟它相對應的另一個關鍵字是implicit,意思是隱藏的,類構造函數默認情況下即聲明爲implicit(隱式)。
強制類型準換說明:當構造函數的聲明變爲
explicit Stonewt(double lbs);
時,將關閉上面示例中的隱式轉換,變爲顯示強制類型轉換:
Stonewt myCat;
myCat = 19.6; //錯誤
myCat = Stonewt(19.6); //OK
myCat = (Stonewt) 19.6; //OK,舊式表達方法
將 stonewt.h中的帶有一個參數的Stonewt構造函數加上explicit時:
explicit Stonewt(double lbs);
運行時會出現如下錯誤提示:
說明explicit強制類型轉換起作用了,隱式轉換不被允許。
參考:《C++ Primer Plus》 (第六版),p411-415.