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