2 conversion function 转换函数

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 在之前出现过