条款24:若所有参数皆需类型转换,请为此采用non-member函数

    科技2022-07-10  93

    考虑如下支持算数运算的类

    class Rational { public: Rational(int numerator = 0, int denominator = 1); int numerator() const; int denominator() const; //分子,分母函数 const Rational operator* (const Rational& lhs) const; //乘法函数 private: // ... };

    将两个有理数以最轻松自在的方式相乘

    Rational oneEighth(1, 8); Rational oneHalf(1, 2); Rational result = oneHalf * oneEighth;// 正确 result = result * oneEighth;// 正确

    但是当你希望支持混合运算时…比如拿Rational和int相乘…

    result = oneHalf * 2; // 正确 result = 2 * oneHalf; // 错误

    上述问题当你以对应函数形式重写两个式子时,问题便一目了然(因为2没有对应的成员函数operator*提供调用)

    result = oneHalf.operator*(2); result = 2.operator*(oneHalf);

    同时编译器也会在non-memner中寻找operator*函数,但是本例子并不存在这样的non-member函数

    result = oneHalf * 2注意这里的第二个参数是2,但是Rational::operator*需要的实参却是个Rational对象,这里发生了隐式类型转换;等价于如下动作

    const Rational temp(2); result = oneHalf * temp;

    如果构造函数改为explicit类型,则result = oneHalf * 2; 和result = 2 * oneHalf;都无法通过编译 最终想要支持混合算术运算的方法是让operator *成为一个non-member函数

    const Rational operator* (const Rational& lhs, const Rational& rhs) { return Rational(lhs,numerator() * rhs.nmerator(), lhs.denominator() * rhs.denominator()); } Rational oneFourth(1, 4); Rational result; result = oneFourth * 2; result = 2 * oneFourth; //万岁,编译通过
    Processed: 0.013, SQL: 8