C++-使用类(类的自动转换和强制类型转换)
使用类-类的自动转换和强制类型转换
可以将类定义成与基本类型或另一个类相关,使得从一种类型转换为另一种类型是有意义的。 在这种情况下,程序员可以指示C++如何自动进行转换,或通过强制类型转换来完成。
(1) stonewt.h
//stonewt.h
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
enum { Lbs_per_stn = 14 }; //一英石=14磅
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs); //double类型磅的构造函数
Stonewt(int stn, double lbs); //英石、磅的构造函数
Stonewt();
~Stonewt();
void show_lbs() const; //用磅格式显示重量
void show_stn() const; //用英石格式显示重量
};
#endif // !STONEWT_H_
(2) stonewt.cpp
//stonewt.cpp
#include<iostream>
using std::cout;
#include"stonewt.h"
//double值的Stonewt对象构造函数
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs) % Lbs_per_stn+lbs - int(lbs);
pounds = lbs;
}
//英石、double值的Stonewt对象构造函数
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt()
{
}
//用英石显示重量
void Stonewt::show_stn() const
{
cout << stone << " stone," << pds_left << " pounds\n";
}
//用磅显示重量
void Stonewt::show_lbs() const
{
cout << pounds << " pounds\n";
}
在C++中,接受一个参数的构造函数为将类型与该参数相同的值转换为类提供了蓝图。 因此,下面的构造函数用于将double类型的值转换为Stonewt类型:
Stonewt(double lbs); //double-Stonewt类型转换的模板
也就是说,可以编写这样的代码:
StonewtmyCat; //创建一个Stonewt对象
myCat =19.6; //用Stonewt(double)将19.6转换为Stonewt类型
只有接受一个参数的构造函数才能作为转换函数。
C++新增了关键字explicit,用于关闭这种自动特性。 也就是说,可以这样声明构造函数:
explicit Stonewt(double lbs); //不允许隐式转换
这将关闭上述示例中介绍的隐式转换,但仍然允许显示转换,即显式强制类型转换:
StonewtmyCat; //创建一个Stonewt对象
myCat = 19.6; //如果Stonewt(double)被声明为explicit则无效
mycat = Stone(19.6); //可以,显式转换
mycat =(Stonewt) 19.6; //可以,老式显式转换
(3) stone.cpp
//stone.cpp
#include<iostream>
using std::cout;
#include"stonewt.h"
void display(const Stonewt & st, int n);
int main()
{
Stonewt incognito = 275; //使用构造函数初始化
Stonewt wolfe(285.7); //和Stonewt wolfe=285.7相同
Stonewt taft(21, 8);
cout << "The celebrity weighed ";
incognito.show_stn();
cout << "The detective weighed ";
wolfe.show_stn();
cout << "The president weighed ";
taft.show_lbs();
incognito = 276.8; //使用构造函数进行转换
taft = 325; //和taft = Stonewt(325)相同
cout << "After dinner, the celebrity weighed: ";
incognito.show_stn();
cout << "After dinner, the president weighed: ";
taft.show_lbs();
display(taft, 2);
cout << "The wrestler weighed even more.\n";
display(422, 2); //将422转换为double类型,进而转换为Stonewt类型
cout << "No stone left unearned\n";
std::cin.get();
return 0;
}
void display(const Stonewt& st, int n)
{
for (int i = 0; i < n; i++)
{
cout << "Wow! ";
st.show_stn();
}
}
当构造函数只接受一个参数时,可以使用下面的格式来初始化对象:
//当使用带有一个参数的构造函数初始化一个类对象时的语法
Stonewtincognito = 275;
这等价于前面介绍过的另外两种格式:
//初始化类对象的标准语法
Stonewt incognito(275);
Stonewt incognito = Stonewt(275);
然而,后两种格式可用于接受多个参数的构造函数。
最后,请注意下面的函数调用:
display(422,2); //将422转换为double类型,进而转换为Stonewt类型
display()原型表明,第一个参数应是Stonewt对象。 遇到int参数时,编译器查找构造函数Stonewt(int),以便将该int转换为Stonewt类型。 由于没有找到这样的构造函数,因此编译器寻找接受其他内置类型(int可以转换为这种类型)的构造函数。Stone(double)构造函数满足这种条件,因此编译器将int转换为double,然后使用Stonewt(double)将其转换为一个Stonewt对象。
(4) 转换函数
构造函数只用于从某种类型到类类型的转换。 要进行相反的转换,必须使用特殊的C++运算符函数——转换函数。
转换函数是用户定义的强制类型转换,可以像使用强制类型转换那样使用它们。 例如,如果定义了从Stonewt到double的转换函数,就可以使用下面的转换:
Stonewtwolfe(285.7);
double host = double(wolfe); //语法#1
double thinker = (double)wolfe; //语法#2
也可以让编译器来决定如何做:
Stonewtwells(20, 3);
double star = wells; //转换函数的隐式调用
编译器发现,右侧是Stonewt类型,而左侧是double类型,因此它将查看程序员是否定义了与此匹配的转换函数。(如果没有找到这样的定义,编译器将生成错误消息,指出无法将Stonewt赋给double。)
要转换为typeName类型,需要使用这种形式的转换函数:
operator typeName();
注意:
转换函数必须是类方法;
转换函数不能指定返回类型;
转换函数不能有参数。
要添加将stonewt对象转换为int类型和double类型的函数,需要将下面的原型添加到类声明中:
operatorint();
operatordouble();
stonewt1.h
//stonewt1.h
#ifndef STONEWT_H_
#define STONEWT_H_
class Stonewt
{
private:
enum { Lbs_per_stn = 14 }; //一英石=14磅
int stone;
double pds_left;
double pounds;
public:
Stonewt(double lbs); //double类型磅的构造函数
Stonewt(int stn, double lbs); //英石、磅的构造函数
Stonewt();
~Stonewt();
void show_lbs() const; //用磅格式显示重量
void show_stn() const; //用英石格式显示重量
//转换函数
operator int() const;
operator double() const;
};
#endif // !STONEWT_H_
(5) stonewt1.cpp
//stonewt1.cpp -- Stonewt类方法+转换函数
#include<iostream>
using std::cout;
#include"stonewt1.h"
//double值的Stonewt对象构造函数
Stonewt::Stonewt(double lbs)
{
stone = int(lbs) / Lbs_per_stn;
pds_left = int(lbs) % Lbs_per_stn+lbs - int(lbs);
pounds = lbs;
}
//英石、double值的Stonewt对象构造函数
Stonewt::Stonewt(int stn, double lbs)
{
stone = stn;
pds_left = lbs;
pounds = stn * Lbs_per_stn + lbs;
}
Stonewt::Stonewt()
{
stone = pounds = pds_left = 0;
}
Stonewt::~Stonewt()
{
}
//用英石显示重量
void Stonewt::show_stn() const
{
cout << stone << " stone," << pds_left << " pounds\n";
}
//用磅显示重量
void Stonewt::show_lbs() const
{
cout << pounds << " pounds\n";
}
//转换函数
Stonewt::operator int() const
{
return int(pounds + 0.5);
}
Stonewt::operator double() const
{
return pounds;
}
(6) stone1.cpp
程序stone1.cpp对新的转换函数进行测试。 该程序中的赋值语句使用隐式转换,而最后的cout语句使用显式强制类型转换。
//stone1.cpp
#include<iostream>
#include"stonewt1.h"
void display(const Stonewt & st, int n);
int main()
{
using std::cout;
Stonewt poppins(9, 2.8); //9英石,2.8磅
double p_wt = poppins; //隐式转换
cout << "Convert to double => ";
cout << "Poppins: " << p_wt << " pounds.\n";
cout << "Convert to int => ";
cout << "Poppins: " << int(poppins) << " pounds.\n";
std::cin.get();
return 0;
}
(7) 转换函数和友元函数
下面为Stonewt类重载加法运算符。
假设没有定义operator double()转换函数。 可以使用下面的成员函数实现加法。
Stonewt Stonewt::operator+(const Stonewt & st) const
{
double pds = pounds + st.pounds;
Stonewt sum(pds);
return sum;
}
也可以将加法作为友元函数来实现,如下所示:
Stonewt operator+(const Stonewt & st1,const Stonewt & st2)
{
double pds = st1.pounds+st2.pounds;
Stonewt sum(pds);
return sum;
}
可以提供方法定义或友元函数定义,但不能都提供。 上面任何一种格式都允许这样做:
StonewtjennySt(9, 12);
StonewtbennySt(12, 8);
Stonewt total;
total =jennySt + bennySt;
另外,如果定义了Stonewt (double)函数,则也可以这样做:
StonewtjennySt(9, 12);
double kennyD= 176.0;
Stonewt total;
total =jennySt + kennyD;
但只有友元函数才允许这样做:
StonewtjennySt(9, 12);
double pennyD= 146.0;
Stonewt total;
total =pennyD + jennySt;
这里的经验是,将加法定义为友元函数可以让程序更容易适应自动类型转换。
上一篇: jquery解析json拼接到下拉框(含jar包)
下一篇: 强大,Nginx配置一键生成