• effective C++ 条款 24:若所有参数皆需类型转换,请为此采用nonmember函数


    令class支持类型隐式转换通常是个糟糕的主意。当然这条规定在建立数值类型时,有例外。假设一个class用来表现有理数,允许整数

    隐式转换为”有理数似乎很合理。

    class Rational{
    public:
        Rational(int numerator = 0, int denominator = 1); //刻意不为explicit;允许int-to-Rational隐式转换
        int numerator()const;
        int denominator()const;
    };

    在支持算术运算符时考虑该由member函数、还是non-member函数来实现:

    先看成员函数的写法:

    class Rational{
    public:

        const Rational operator*(const Rational& rhs)const;
    };

    Rational oneEight(1,8);

    Rational onehalf(1,2);

    Rational result = oneHalf * oneEight;//nice

    result = result * oneEight;//ok

    但是你希望支持混合运算:

    result = oneHalf * 2;//ok 2发生了隐式类型转换

    result = 2 * oneHalf;//wrong !

    这样便一目了然:

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

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

    oneHalf是一个含operator*函数的class的一个对象。2没有相应的class,编译器会尝试寻找可被以下这般调用的non-member operator*(也就是在命名空间内 或 global作用域内):

    result = operator*(2, oneHalf);//wrong!

    本例不存在这样一个接受int和Rational作为参数的non-member operator* 因此查找失败。

    只有当参数被列于参数列(parameter list)内,这个参数才是隐式类型转换的合格参与者地位相当于“被调用之成员函数所隶属的那个对象”——即this对象——的那个隐喻参数,绝不是隐式转换的合格参与者

    为了支持混合运算。让operator* 成为一个non-member函数,便允许编译器在每一个实参身上执行隐式类型转换:

    const Rational operator*(const Rational& lhs, const Rational& rhs)
    {
        return Rational(lhs.numerator() * rhs.numerator(), lhs.denominator() * rhs.denominator());
    }

    result = 2 * oneHalf;//ok!终于编译通过了!

    operator*是否要成为Rational的friend函数呢?答案是否定的,因为operator*完全籍由Rational的public接口完成任务;无论何时如果你可以避免friend函数就该避免。

    当让Rational成为一个class template, 又有一些新争议、解法、牵连形成了 条款46

  • 相关阅读:
    vi/vim 如何添加和删除多行注释
    linux报错:命令未找到
    删除远程分支的方法
    k-vim常见快捷键
    [转]常见linux命令用法介绍
    python库termcolor用法
    gitignore样例解析
    [转]"git rm" 和 "rm" 的区别
    python中的slice用法
    牛客网linux试题-错误整理-20170914
  • 原文地址:https://www.cnblogs.com/lidan/p/2327774.html
Copyright © 2020-2023  润新知