本文介绍一下C++的转换函数,例子是基于侯捷老师的关于一个分数类的例子,然后加上我自己的一些理解。
一 类转换为其他类型
类转换为其他类型,这里的其他类型可以是任何类型,如int、double甚至是你定义的一个类,至于怎么写,就是设计的人的事情了。
下面我以转换为double型为例,请看下面的例子:
#include <iostream>
#include <string>
using namespace std;
class Fraction
{
public:
Fraction(int num, int den = 1)
:numerator(num), denominator(den){}
operator double() const
{
return ( numerator*1.0 / denominator);
}
operator string() const
{
return to_string(numerator) + '/'+ to_string(denominator);
}
private:
int numerator;
int denominator;
};
int main()
{
Fraction f(3,5);
double d = f + 4.3;
cout << d << endl;
string s = f;
cout << s << endl;
system("pause");
return 0;
}
注意上面:operator double() const 和operator string() const 就是两个转换函数。其语法是:operator type()。它不需要参数,也不要返回值,返回值type实际上就已经决定了。(注,const只是把成员函数变为常量成员函数)。 运行结果如下:
二 non-explicit one argument 构造函数
one argument的意思是我们只要给一个参数就行,尽管它实际的形参可能有多个。
还以上面的例子为基础,其实构造函数Fraction(int num, int den = 1) 就是转换函数,其特点是只传一个参数,其他参数使用默认 。
测试如下:
int main()
{
Fraction f1 = f + 4.3;
cout << f1 << endl;
system("pause");
return 0;
}
在上面中:
- f先转换为double型,
- 然后和4.3相加,结果为4.9
- 最后4.9作为参数传入Fraction的类构造函数,也即执行double到Fraction的转换
打印的结果很明显就是4。因为虽然传入的是4.9,但是由于构造的参数是整型,转换后为4。
请思考:这里为什么不是先把4.3转换为Fraction类类型? 其实很简单,因为我们并没有定义Fraction的加法,所以编译器在转换时,这条路是走不通的。
三.别让编译器帮你做选择
前一节的最后部分我给了一个思考,并给出了原因。现在我们来定义一个Fraction的加法,即重载+,且是做成员函数,像下面这样:
#include <iostream>
#include <string>
using namespace std;
class Fraction
{
Fraction operator+(const Fraction& f)
{
return Fraction(this->numerator * f.denominator + this->denominator * f.numerator,
f.denominator * this->denominator);
}
};
int main()
{
Fraction f(3,5);
double d = f + 4.3;
Fraction f1 = f + 4.3;
system("pause");
return 0;
}
编译时你会发现这样会报错:“Fraction::operator +”: 2 个重载有相似的转换 。原因是在做加法时,有两种选择:将f转为double类型再加和将4.3转为Fraction类型再加。
可是我们知道,编译器是做不了选择的,当面临多种选择时,编译器只能报错。解决方法是:
- 或者将转换函数
operator double() 删掉,此时显而易见,double d = f + 4.3; 会报错。因为此时f + 4.3 是一个Fraction类类型,赋值时无法将Fraction转为double。 - 或者再构造函数前加上关键字
explicit ,这样旨在告诉编译器,不要给我做其他类型到Fraction类类型的转换。此时Fraction f1 = f + 4.3; 会报错,原理和上面的相同,不再赘述。
四.总结
由于转换函数不是很常见,所以关于知识较深的内容我也不太了解,下面就是简单总结一下前面的内容:
- 转换函数的语法是:
operator type() - 对于转换的反方向,用
one-argumen的构造函数 来实现 - explicit关键字可以消除one-argumen的构造函数带来的转换
- 至于运算时(如本例中的加法),1 2 哪个会发生,完全取决于你的设计,记住
别让编译器做选择
|