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

来源:互联网 发布:王坚 阿里云 哲学问题 编辑:程序博客网 时间:2024/05/22 05:01

条款24:若所有参数皆需类型转换,请为此采用non-member函数
(Declare non-member functions when type conversions should apply to all parameters.)

内容:
    平时在我们的coding过程当中,我们有时候会碰到这样一些情况:我传进去的实参与声明函数的形参并不是同
一类型的,函数调用竟然能够成功!这个听起来很不可思议是不是,那么我这里给你说一个编译器的"秘密",也许你在
听完以后,你或许有可能对你说的那些"不可思议的事情"就不以为然了.
    我在这里要说的"秘密"就是:当函数的实参类型与形参的出现不一致时候,编译器会尽它最大的能力去寻找合理
类型转换方案进行隐式转换,使它们之间的类型达到一致,从而完成函数的调用过程,当然如果最后还是没有找到合
适的类型转换策略,编译器就会给出"类型不匹配"的编译错误.不怎么理解?好,下面我来举个例子来说明这个问题.
    假设现在有一个内置类型int的代理类IntDelegate,当然它就有很多特性,而这里我们要说的是它的乘法操作,
你自然就写出了如下的代码:
    class IntDelegate{
    public:
        IntDelegate(int value = 0):intValue_(value){}
        IntDelegate(const IntDelegate& rhs){
            intValue_ = rhs.intValue_;
        }
        const IntDelegate operator*(const IntDelegate& rhs){
            IntDelegate result;
            result.intValue_ = intValue_ * rhs.intValue_;
            return result;
        }
        int getValue()const{
            return intValue_;
        }
        ...
    private:
        int intValue_;
        ...
    };
    wow,写的不错,下面我们来看看有没有什么问题,怎么去看?晕,"实践是检验真理的唯一标准",写代码测试一下:
    //test.cpp
    ...
    IntDelegate a(1),b(2);
    IntDelegate c = a*b; //ok.
    c = a * 2;           //Line1: ok.
    c = 2 * a;           //Line2: error,喔欧,乘法交换律失败罗!shit!
    我们先来看Line1,你这里奇怪了?咦?这里的2压根就不是IntDelegate类型,怎么也能编译的过?请注意
IntDelegate的构造函数是一个非explicit构造函数,这也就意味着编译器可以对它进行隐式转换,这种转换等价
代码如下:
    IntDelegate tempt(2);
    c = a * tempt;
    Line1现在该理解了吧?呵呵,我们接着来看Line2,这里的2为什么不能拥有上面的隐式转换呢?原因很简单:只有
位于参数列表内的参数才是隐式转换的合格参与者.显然这里的a才是那位合格者,呜呜....,不公平,我需要两个都能
够进行转换.喔,问题不大!你想想,既然只有作为参数列表才能进行隐式转换,我们这里就很自然地想到把2也作为参
数列表中的一员,这样不就搞定了嘛,呵呵!我们来修改一下代码,这里我们就需要变换一下操作符*的实现函数的函数
原型:
    const IntDelegate operator*(const IntDelegate& lhs,const IntDelegate& rhs){
        return IntDelegate(lhs.getValue()*rhs.getValue());
    }
    在运行一下上面的测试代码,全部通过,结果完全真确,恭喜你!

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