您的位置:首页 > 编程语言 > C语言/C++

C++之单目运算符重载

2016-06-04 11:16 351 查看
这里以“-”(负号,不是减号)为例:

先用成员函数重载来实现:

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;
}


单目运算符重载就说到这,还是要多联系,多敲代码才是王道。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: