C++之单目运算符重载

来源:互联网 发布:粤知一二骑马过海 编辑:程序博客网 时间:2024/05/21 17:26

这里以“-”(负号,不是减号)为例:
先用成员函数重载来实现:

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

单目运算符重载就说到这,还是要多联系,多敲代码才是王道。

0 0
原创粉丝点击