自动转换
在C++中,接受一个参数的构造函数将类型与该参数类型相同的值转换为类。为此可以这样编写代码
ST(double lb); //此为ST类的构造函数
//用于将double类型的值转换为ST类型
//于是可以有
ST myCat;
myCat=19.6; //将19.6转换为ST类
ST(int i,double lb=1); //这种情况也可以自动转换
ST mt;
mt=12;
上述第一个赋值语句右边先利用构造函数创建临时对象,并将19.6作为初始值,然后再将该临时对象赋值给myCat。该过程为隐式转换,自动进行。
但这种自动转换并不总是程序员期望的,为此C++增添了explicit关键字来关闭这种特性。
//可以这样声明函数来关闭自动转换
explicit ST(double lb);
ST myCat;
myCat=19.6; //不允许
myCat=ST(19.6); //显式调用构造函数,允许
myCat=(ST) 19.6; //强制类型转换,允许
如果没有使用关键字explicit,除了显式强制转换,ST(double lb)构造函数还可用于下列隐式转换
- ST对象初始化为double值。
- double值赋给ST对象。
- double值赋给接受ST参数的函数。
- 返回值声明为ST的函数试图返回double值时。
- 上述任意一种情况下,使用可转换为double的类型时。(例如使用int,会先转换为double再转换为类。)
注意:最后一种情况需保证不存在二义性,例如同时定义了ST(double lb)和ST(long ac),使用int值就会导致二义性。
转换函数
前面可以将数字转换为ST对象,而相反的转换也是可以实现的。这需要使用特殊的C++运算符函数——转换函数。如果定义了从ST到double的转换函数,就可以使用下面的转换。
ST wo(285.7)
double host=double (wo);
double th=(doule) wo;
//也可以由编译器决定
ST wells(20,3)
double star=wells; //如果有转换函数,则会自动调用,否则报错
想要定义一个转换函数需要注意以下几点
- 转换函数必须是类方法
- 转换函数不能指定返回类型
- 转换函数不能有参数
//标准格式
operator typeName(); //typeName表示要转换的类型
operator double(); //表示double类型的转换函数
//该声明指出转换的类型,故无需返回类型
//该声明通过对象调用,故无需参数
//相关定义如下
ST::operator double()
{
return pounds; //pounds为ST类中的double值
}
若存在同时存在两个可以相互转换的内置类型对应的转换函数,在无显式转换的情况下会出现二义性错误。对此我们可以使用显式强制转换来指出要使用哪个转换函数。
class ST{
...
ST(int stn,double lb);
operator int()const;
operaror double()const;
}
...
ST po(9,2.8);
...
long gone=(double)po; //显式转换为double类型
long go=(int)po; //显式转换为int类型
转换函数也存在隐式自动转换,可以使用关键字explicit来禁止。也可以用一个功能相同的非转换函数来替换该转换函数。这样仅在被显式调用地调用时,该函数才会被执行。
explicit operator int() const;
explicit operator double() const;//使用explicit关键字,使得隐式转换被禁止
//也可以使用非转换函数
ST::operator int(){return int(pounds);}
//改为
int ST::suo(){return int(pounds);}
类与内置类型的加法实现
想要double值和ST类对象相加,有两种选择。第一种是下列声明友元
friend operator+(const ST&,const ST&);
//double类型参数通过ST(double)构造函数自动转化为ST对象再进行加法
第二种是重载加法运算符为一个显式使用double类型的参数
ST operator+(double x);
friend ST operator+(double x,ST&s);
//则有下列语句
total=j+k;//j为ST对象,k为double值,与ST operator+(double x)完全对应
total=k+j;//与friend ST operator+(double x,ST&s)完全对应
//也可以使用两个友元函数重载运算符
第一种方法代码简短但依赖于隐式转换,运行时间长。第二种代码更长,但不依赖于隐式转换,运行时间更短。
注:若上述语句同时定义了转换函数将出现二义性错误,即可能将其解释为double加法而非类加法。