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

0.概述

如果需要为某个函数的所有参数(包括被this 指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member。

1.例:有理数类

class Rational {
    public:
        Rational(int numerator = 0, // ctor is deliberately not explicit;
        int denominator = 1); // 允许隐式转换int-to-Rational
        // conversions
        int numerator() const; // accessors for numerator and
        int denominator() const; // denominator — see Item22
    private:
        ...
};

1.1 将operator*写为成员函数

class Rational {
public:
    ...
    const Rational operator*(const Rational& rhs) const;
};

使用示例:

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

尝试混合式运算:

result = oneHalf * 2; // 可
result = 2 * oneHalf; // 报错!

上式中的乘法显然不满足交换律,以对应的函数形式重写两个式子:

result = oneHalf.operator*(2); // fine
result = 2.operator*(oneHalf); // error!

oneHalf是一个内含operator*函数的class的对象,所以编译器调用该函数。然而整数2并没有相应的class,也就没有operator*成员函数。编译器也会尝试寻找非成员operator*(也就是在命名空间内或在global作用域内):

result = operator*(2, oneHalf);

但这样的函数在本例中并不存在,查找失败。

那为什么第一个调用式子可以通过?发生了隐式类型转换(通过构造函数)。

const Rational temp(2); // create a temporary Rational object from 2
result = oneHalf * temp; // same as oneHalf.operator*(temp);

如果构造函数是explicit,则两个式子都无法通过编译。

1.2 使operator*成为非成员函数

并允许编译器在每个实参上执行隐式类型转换,就可以支持混合式算术运算

class Rational {
    ... // contains no operator*
};
const Rational operator*(const Rational& lhs, const Rational& rhs) //非成员函数
{
    return Rational(lhs.numerator() * rhs.numerator(),
    lhs.denominator() * rhs.denominator());
}
Rational oneFourth(1, 4);
Rational result;
result = oneFourth * 2; // fine
result = 2 * oneFourth; // hooray, it works!

还有一点需要考虑:operator*是否该成为友元函数?

不,成员函数的反面是非成员函数而非友元函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值