C++之单目运算符重载

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

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

运行结果如下:
C++之单目运算符重载_第1张图片

可以看出没有错,这里要注意,进行负号操作,并没有改变对象值的本身,所以这里不能直接操作对象本身,需要重建一个新对象,下面多加一步操作:

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

运行结果是这样的:
C++之单目运算符重载_第2张图片

可以看到结果是正确的。返回类型为什么是引用类型这里就不重复解释了,双目运算符重载中有说明。
同时,也可以看出,前- -是可以作为左值的。

再给出个友元重载:

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

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

你可能感兴趣的:(C++)