c++多态之运算符重载

1 运算符重载规则

(1)除了少数的运算符不能重载(类属关系运算符“,”、作用域分辨符“::”、三目运算符“?:”成员指针运算符“.*”),大部分都可以重载。
(2)重载之后的运算符的优先级和结合性都不会改变。
(3)不能改变原运算符的操作对象个数,同事至少有一个操作对象是自定义类型。

运算符重载的形式有两种,成员函数和非成员函数
成员函数的一般语法形式为:

换回类型 operator 运算符(形参表)
{
	函数体
}

非成员函数的一般语法形式为:

在这里插入代码片
换回类型 operator 运算符(形参表)
{
	函数体
}

重载为非成员函数时,有时需要涉及私有成员,这是可以声明为友元函数
当重载为成员函数时,参数个数比原来的操作数个数少一个(后置“++”,“–”除外),因为这里第一个操作数就是这个类中的对象,不用再出现在参数表中。

运算符重载为成员函数

这有又分两种情况一种是双目运算符,一种是单目运算符

双目运算符重载例子:

#include <iostream>

using namespace std;

class Complex{
public:
    Complex(double r=0.0,double i=0.0):real(r),imag(i) {}
    Complex operator+(const Complex &c2) const;      //双目运算符重载为成员函数
    Complex operator-(const Complex &c2) const;
    void display() const;
private:
    double real;
    double imag;
};

Complex Complex::operator+(const Complex &c2) const
{
    return Complex(real+c2.real,imag+c2.imag);    //创建一个临时无名对象作为换回值,也可以在一开始创建一个对象,把值赋值给这个对象,然后在换回
}

Complex Complex::operator-(const Complex &c2) const
{
    return Complex(real-c2.real,imag-c2.imag);
}

void Complex::display() const
{
    cout << "(" << real << "," << imag << ")" << endl;
}

int main()
{
    Complex c1(5,4), c2(2,10),c3;
    cout << "c1=";c1.display();
    cout << "c2=";c2.display();
    c3=c1-c2;
    cout << "c3=c1-c2=";c3.display();
    c3=c1+c2;
    cout << "c3=c1+c2=";c3.display();

    return 0;
}

最后结果:

在这里插入图片描述
这里重载以后的“+、-”并未改变原有的功能,对于基本型数据类型的运算遵循c++预定于规则,这样既有了原有的功能,又增加了新的复数运算功能,体现了c++广泛的多态性。
单目运算符例子:

#include<iostream>
using namespace std;

class Clock
{
public:
    Clock(int hour=0,int minute=0,int second=4);
    void showTime() const;
    Clock operator++();      //重载规定,前置单目运算符重载为函数试没有形参。
    Clock operator++(int);  //int型参数在函数体中并未使用,只是为了区分前置与后置
private:
    int hour,minute,second;
};

Clock::Clock(int hour,int minute,int second)
{
    this->hour = hour;
    this->minute = minute;
    this->second = second;
}

void Clock::showTime() const
{
    cout << hour << ":" << minute << ":" << second << endl;
}

Clock Clock::operator++()       //前置++重载
{
    second++;
    if(second>=60)
    {
        second-=60;
        minute++;
        if(minute>=60)
        {
            minute-=60;
            hour=(hour+1)%24;
        }
    }
/*
在这里注意this/*this,this是指向自身对象的指针,*this是自身对象
*/
    return *this;     
}

Clock Clock::operator++(int)
{
    Clock old = *this;
    ++(*this);
    
    return old;
}

int main()
{
    Clock myClock(23,59,59);
    cout << "First time output:";
    myClock.showTime();
    cout << "Show myClock++: ";
    
    (myClock++).showTime();     
    myClock.showTime();           
/*
在这里要注意这个两个得到的结果不一样,个人认为是在上一个  (myClock++).showTime();他是先执行myClock.showTime();,
然后在执行myClock++,接着在执行myClock.showTime(); 这里还要注意在执行myClock++时,在Clock Clock::operator++(int)
中有一个++(*this),这里又回归到前置++的重载。
*/     
    cout << "Show ++myClock:  ";
    (++myClock).showTime();
    return 0;
}

运算符重载为非成员函数

运算符重载为非成员函数时,如果不是为了访问参数对象的私有成员,尽量不要把将其设置为类的友元函数
下面通过一个例子说明:

#include <iostream>
using namespace std;

class Complex
{
public:
    Complex(double r=0.0,double i=0.0):real(r),imag(i) {}
    friend Complex operator+(const Complex &c1,const Complex &c2);
    friend Complex operator-(const Complex &c1,const Complex &c2);
    friend ostream &operator<<(ostream &out,const Complex &c);

private:
    double real;
    double imag;
};

Complex operator+(const Complex &c1,const Complex &c2)
{
    return Complex(c1.real+c2.real,c1.imag+c2.imag);
}

Complex operator-(const Complex &c1,const Complex &c2)
{
    return Complex(c1.real-c2.real,c1.imag-c2.imag);
}


ostream &operator<<(ostream &out,const Complex &c)
{
    out<<"("<<c.real<<","<<c.imag<<")";
    return out;
}


int main()
{
    Complex c1(5,4),c2(2,10),c3;
    cout << "c1=" << c1 << endl;
    cout << "c2=" << c2 << endl;
    c3 = c1 - c2;
    cout << "c3=c1-c2=" << c3 << endl;
    c3 = c1 + c2;
    cout << "c3=c1+c2=" << c3 << endl;

    return 0;
}

这里“+、-”与重载为成员函数中的“+、-”想类似,不同就是变成了类的友元和传递的参数多一个。
还有一个问题就是这里"<<“运算符重载,ostream是cout类型的一个基类,ostream &operator<<(ostream &out,const Complex &c)是什么含义,首先第一个ostream &为了能达到cout<<对象<<对象<<endl;的连续输出对象的效果,第二个”<<“运算符的左操作数是第一个”<<"运算符的换回结果,设置返回类型为引用。第二个表示是输出的类类型的引用。

输出结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42711815/article/details/87925132