若所有参数都需要类型转换,请采用non-member函数
一、 请看例子,有一个TyPoint的类:
class TyPointEx{
private:
int x{0};
int y{ 0 };
public:
TyPointEx(int a = 0, int b = 0)
{
x = a;
y = b;
}
void showTyPointx()
{
cout << "x:" << x << " y:" << y << endl;
}
int GetPointx() const
{
return x;
}
int GetPointy() const
{
return y;
}
};
现在有个需求,就是要支持算数运算,比如加、减等,但这个算数重载运算函数是写成成员函数,还是非成员函数呢??
a.先写成成员函数试试
const TyPointEx &operator+(const TyPointEx & p)
{
x = x + p.x;
y = y + p.y;
return *this;
}
则有:
TyPointEx t(3, 4);
TyPointEx t1(10, 23);
TyPointEx temp = t + 2;//编译通过
t.showTyPointx();
TyPointEx temp1 = 2 + t;//编译出错
为什么 TyPointEx temp1 = 2 + t;编译会出错呢???
其实吧,所有的运算符重载其实最终调用的都是函数而已,你看到的 t1+t2;===>实际上是:t1.operator+(t2);
我想现在你应该明白为什么2+t编译出错,而t+2正确了。其实这里2+t;没有找到相应的函数可调用,编译器还试图调用非成员函数operator+(2,t);
但我们并没有实现它。所以出错。
b.非成员函数出场
const TyPointEx &operator+(const TyPointEx & p,const TyPointEx & p1)
{
return TyPointEx(p.GetPointx()+p1.GetPointx(),p1.GetPointy()+p.GetPointy());
}
此时两句都能通过编译。
在此我要提一个小知识点那就是关键字explicit,这个是c++11中的新知识,如果给构造函数前面加这个关键字,那么这两句没有一个可以编译成功,因为这个关键字的作用是阻止构造函数进行隐式转换。
其实无论是调用成员函数的重载,还是非成员函数的重载,最终都将经过了隐式转换。一般的话如果让类支持隐式转换是很糟糕的事情,但是在涉及数值类的时候还是很方便的。
TyPointEx t(3, 4);
TyPointEx t1(10, 23);
TyPointEx temp = t + 2;//编译通过
t.showTyPointx();
TyPointEx temp1 = 2 + t;//编译出错
temp1.showTyPointx();
结果:
c.有的人可能会疑问,是否要将operator+()函数,改为友元函数,我的出发点是:能不用友元就不要用友元,友句话说得好,朋友带来的价值往往比麻烦少。