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 


版权声明:本文为m0_37360684原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。