C++之若所有参数皆需类型转换,请为此采用non-member函数(24)---《Effective C++》

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

请参看如下代码:

class A{
public:
    A(int xx):x(xx){
    }
    int getX() const;
private:
    int x;
};

现在我们需要对类A进行乘法运算,现在有两种方式可以选择。
1)member函数重载operator *运算符:

class A{
    ...
    A operator*(const A& AB) const{
        this->x*=AB.x;
        return *this;
    }
    ...
};

我们可以发现,此时可以得出正确答案,那么此时我们改变一下代码呢?

#include <iostream>
#include <string>
using namespace std;
class A{
public:
    A(int xx) :x(xx){
    }
    int getX() const;
    A operator*(const A& AB){
        this->x *= AB.x;
        return *this;
    }
    void show(){
        cout << x << endl;
    }
private:
    int x;
};
int main(){
    A a1(10);
    a1 = a1 * 2;
    a1.show();
    a1 = 2 * a1;
    a1.show();
}

可以发现函数报错,其中a1=a1*2时正常,a1=2*a1是后函数报错,错误为没有与这些操作数匹配的 “*” 运算符,分析一下原因:

  • a1=a1*2执行正确,因为类A的构造函数我们声明为non-explicit的,即可以进行隐式转化,那么当执行该语句的时候,先执行2->A(2)的隐式类型转换,然后调用A的operator*函数,主要是调用了类A的operator *函数,代码执行正确;

  • a1=2*a1执行错误,为什么呢?等价于a1=2.operator*(a1),整数2并没有相应的类,也没有定义operator *(const A& a)的重载符,因此查找失败。

    让我们对上面两种情况进行总结,可以看出,至于当参数位于参数列时候,同时当函数的构造函数是non-explicit时候,才会发生所谓的类型转换,如果参数并没有位于参数列或者函数的构造函数被声明为explicit的时候,则类型转换失败!

2)我们可以将其声明为non-member成员函数,见如下代码:

#include <iostream>
#include <string>
using namespace std;
class A{
public:
    A(int xx) :x(xx){
    }
    int getX() const{
        return x;
    };
    void show(){
        cout << x << endl;
    }
private:
    int x;
};
A operator*(const A& a, const A& b){
    A temp = a.getX()*b.getX();
    return temp;
}
int main(){
    A a1(10);
    a1 = a1 * 2;
    a1.show();
    a1 = 10 * a1;
    a1.show();
    return 0;
}

运行结果为:
这里写图片描述
可以发现此时针对A的乘法运算满足交换律,这才是我们想要的针对A的乘法运算,注意这儿我们并没有将operator *声明为friend函数,因为getX()可以获得数据成员,为了封装性考虑,我们能避免使用friend就尽量避免使用friend,member的对立面是non-member,member的近义词是friend关键字,希望大家注意一下!

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值