C++類的自動轉換:類型轉換函數

一、通常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.

https://www.cnblogs.com/rednodel/p/9299251.html 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章