这里以“-”(负号,不是减号)为例:
先用成员函数重载来实现:
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
Complex operator-(){
Complex t;
t._x = -this->_x;
t._y = -this->_y;
return t;
}
};
int main()
{
int a = 10;
cout << -a << endl;
cout << -(-a) << endl;
cout << "------------------" << endl;
Complex c(1, 1);
Complex t(2, 2);
(-c).dis();
(-(-c)).dis();
return 0;
}
可以看出没有错,这里要注意,进行负号操作,并没有改变对象值的本身,所以这里不能直接操作对象本身,需要重建一个新对象,下面多加一步操作:
int main()
{
int a = 10;
cout << -a << endl;
cout << -(-a) << endl;
(-a) = 20; //编译报错
cout << "------------------" << endl;
Complex c(1, 1);
Complex t(2, 2);
(-c).dis();
(-(-c)).dis();
(-c) = t;
return 0;
}
运算符重载不变,对于
(-a) = 20;
这么一个普通变量,系统是不允许这么操作的,左值不允许是运算,但
(-c) = t;
缺编译通过了,现在这是不可以的,那么就会说将运算符重载的函数返回值类型改成const就可以了,下面就改一下:
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
const Complex operator-(){
Complex t;
t._x = -this->_x;
t._y = -this->_y;
return t;
}
};
int main()
{
int a = 10;
cout << -a << endl;
cout << -(-a) << endl;
(-a) = 20; //编译报错
cout << "------------------" << endl;
Complex c(1, 1);
Complex t(2, 2);
(-c).dis(); //编译报错
(-(-c)).dis(); //编译报错
(-c) = t; //编译报错
return 0;
}
(-c) = t;的确是报错了,但是
(-c).dis(); //编译报错
(-(-c)).dis(); //编译报错
这两句也同样报错了,因为把返回值类型改成const complex,那么(-c)变成了const对象,当时说const对象时说过const对象必须保证不能修改数据成员,所以只能调用const的成员函数,这里把(-(-c))转换一下:
(c.operator-()).operator-();
第一个c.operator-()返回一个const complex对象,再调用operator-()自然就会出错,又因为dis同样不是const成员函是,两者都报错是必然的。那么再修改一下:
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
void dis() const{
cout << "( " << _x << "," << _y << " )" << endl;
}
const Complex operator-()const{
Complex t;
t._x = -this->_x;
t._y = -this->_y;
return t;
}
};
int main()
{
int a = 10;
cout << -a << endl;
cout << -(-a) << endl;
(-a) = 20; //编译报错
cout << "------------------" << endl;
Complex c(1, 1);
Complex t(2, 2);
(-c).dis();
(-(-c)).dis();
(-c) = t; //编译报错
return 0;
}
这样就只有该报错的报错,不该报错的通过喽。
然后再用友元函数重载一下:
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
void dis() const{
cout << "( " << _x << "," << _y << " )" << endl;
}
friend const Complex operator-(const Complex &a){
Complex t;
t._x = -a._x;
t._y = -a._y;
return t;
}
};
int main()
{
int a = 10;
cout << -a << endl;
cout << -(-a) << endl;
(-a) = 20; //编译报错
cout << "------------------" << endl;
Complex c(1, 1);
Complex t(2, 2);
(-c).dis();
(-(-c)).dis();
(-c) = t; //编译报错
return 0;
}
可以看出来,友元重载有一个参数,而成员函数重载没有参数,跟双目运算符重载一样,友元重载比成员函数重载多一个参数。
还可以看出来这里友元要比成员函数重载略简单一些。而前面+=双目重载则是成员函数重载要简单一些,实际应该用友元重载还是成员函数重载还要自己多敲代码,比较一下那个方便用那个就好。
最后再举个前- -和后- -的例子:
1、前- -
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
Complex& operator--(){
--this->_x;
--this->_y;
return *this;
}
};
int main()
{
int a = 10;
--a;
cout << a << endl;
(--a) = 20;
cout << a << endl;
cout << "-----------------------" << endl;
Complex c(10, 10);
Complex b(20, 20);
(--c).dis();
(--c) = b;
c.dis();
return 0;
}
可以看到结果是正确的。返回类型为什么是引用类型这里就不重复解释了,双目运算符重载中有说明。
同时,也可以看出,前- -是可以作为左值的。
再给出个友元重载:
friend Complex& operator--(Complex &a){
--a._x;
--a._y;
return a;
}
运行结果同样是正确的,在这就不截图了。
2、后- -
class Complex{
private:
float _x;
float _y;
public:
Complex(float x = 0, float y = 0):_x(x), _y(y){}
void dis(){
cout << "( " << _x << "," << _y << " )" << endl;
}
void dis() const{
cout << "( " << _x << "," << _y << " )" << endl;
}
const Complex operator--(int){
Complex t = *this;
this->_x--;
this->_y--;
return t;
}
};
int main()
{
int a = 10;
cout << a-- << endl;
cout << a << endl;
(a--) = 20; //编译报错
cout << "-----------------------" << endl;
Complex c(10, 10);
Complex d = c--;
d.dis();
c.dis();
Complex b(20, 20);
(c--) = b; //编译报错
return 0;
}
后–不同于前- -,比如a- -,先做a = a, 再做 a = a - 1;的操作,同时重载的参数中有一个int的哑元(也就是说有类型,没有名字的参数),重载函数中,要先赋值,再做-1的操作,这里要注意三个问题:
第一个问题:做–操作的对象是谁,是对象本身,还是函数中重新定义的对象t, 当然操作的是对象本身,而并不是对象t;
第二个问题:函数应该返回的是谁,应该返回对象本身,还是对象t,首先知道b = a- -;这里b = a; 还是b = a - 1; 显然b = a; 那么就应该返回t,也就是说对象–之前的值。
第三个问题:后- -操作是不能作为左值的,那么就要返回一个const complex,这样不准改变返回的值,自然就不能当左值了。
同时还有个要说明的,像下面这样:
a----;
c----;
后–是不允许连用的,这也是通过将返回值类型改成const来限制的。而前–是可以连用的,没有const的限制。
再用友元函数重载实现如下:
friend const Complex operator--(Complex & a, int){
Complex t = a;
a._x--;
a._y--;
return t;
}
单目运算符重载就说到这,还是要多联系,多敲代码才是王道。