2 conversion function 转换函数
转换函数, 谁把谁转换成什么呢
你现在设计一个类, 如果叫作 a 的话, 这个叫作 a 的 class 的对象, 可不可以被转换为另外一种类型 ? 这就是一种转换. 或者是另外一种类型可不可以转换成 a, 这个是一个转出去, 一个转进来.
我们先看转出去
class Faction
{
public:
Fraction(int num, int den = 1)
: m_numberator(num), m_denominator(den){}
operator double() const {
return (double)(m_numerator / m_denominator);
}
private:
int m_numerator; // 分子
int m_denominator; // 分母
};
Fraction 分数, 分数其实分子除以分母就是一个 double 类型值
因此我作为一个设计者, 应该可以很合理地认为, Fraction 可以被当成一个 double.
于是我就写一个 operator double()
函数, 这个函数很特别, 它的名字一定是 operator double
中间一定要有空格, 至于要转换成什么类型, 那个类型就成为函数名的一部分, 这里是 double 类型, 所以函数名就是 operator double
. 这个函数的意思就是我这个 Fraction 可以被转为 double, 编译器在任何需要把 Fraction 转换成 double 的时候, 就把这个函数调用一下
因为是转换嘛, 转换拿来什么参数, 所以这么没有参数,.返回类型按理来说, 转换完成之后应该是一个 double, 但是 c++ 说你不用在函数名前面写返回类型, 因为返回类型已经成为函数名的一部分了
operator double
就是一个转换函数, 它的返回类型就是名称里面的这个类型 double
转换这个操作不可能去改变这个类里面的数据, 这个例子里面类里面有分子和分母两个数据, 转换这个过程就是分子除以分母, 分子和分母不应该改变, 所以这种转换函数 通常 都应该加上 const
. 这里说通常的意思是, 如果你没有加 const
, 编译也会通过.
我们在之前的课程中提过, 一个函数没有改变数据就应该加 const
, 如果你没有加, 在一个特殊的情况下也许会出错
函数里面就是具体转换的操作了, 对于分数来说, 转换成 double 就是分子除以分母了
我们现在看一下使用者的例子
Fraction f(3, 5); // 给构造函数传参数, 分子为 3, 分母为 5
double d=4+f; // 调用 operator double, 将 f 转为 0.6
当编译器看到 double d=4+f;
这行代码的时候, 它会去看你有没有对 +
运算符重载, 如果它能找到这样一个函数, 这一行就能编译通过
我们的例子里面没有设计这个函数, 于是乎运算符重装这一条路线就走不通了. 编译器就会看, 看能不能把变量 f, f 是一个 Fraction, 能不能把 f 转换成 double, 于是它就去找你有没有设计这个转换函数. 这里我们有转换函数, 于是编译器就把 5 分之 3 转为 0.6, 于是 d 的值为 4.6
任何一个 class, 只要你认为合理, 你可以写好几个转换函数. 比如你认为分数转换成字符串很合理的话, 你也可以再写一个转换函数 operator string
, 至于这个函数内部怎么操作, 就完全看你自己了
这个转换过去不一定要是基本类型, 任何一个 type 都可以, 只要这个 type 在之前出现过