C++-Assignment operator overloaded function


Preface

Before introducing the assignment operator overloading, let's look at a piece of code:

class Complex    //定义一个复数类
{
    
    
public:
    Complex (double r = 0.0,double i = 0.0) //构造函数
    {
    
    
        _real = r;
        _imag = i;
    }
    void Show()const;
private:
    double _real,_imag;
};
int main()
{
    
    
    //声明2个对象
    Complex a(10,20);
    Complex b (20,30);
    return 0;
}

At this point, what if we need to add a and b? Under normal circumstances, we can naturally think of using the "+" operator to write an expression: "a + b", but unfortunately, an error will be reported when compiling, because the compiler does not know how to deal with this addition, this At that time, we need to write the "+" function that acts on the Complex class object by ourselves, which leads to operator overloading

1. What is the overloaded function of assignment operator?

Assignment operator overloading is to give multiple meanings to existing operators, so that the same operator has different meanings when it acts on different types of data.

Function name: the operator symbol that needs to be overloaded is added after the keyword operator

Function prototype:

返回值类型 operator 运算符 (形参列表)
{
    
    
    //函数体
}

Notes: The essence of operator overloading is function overloading: in the process of implementation, first convert the specified operation expression into a call to the operator, and convert the operand into the parameter of the operator function, and then according to the type of the parameter Determine the function that needs to be called.

Second, talk in detail about the overloaded function of the assignment operator

2.1 Parameter list

Under normal circumstances, the parameter of an assignment operator overloaded function is a reference to the const type of the function's class. The reason for adding const is as follows:

  1. The programmer does not want to make any changes to the value that has been modified with const in the function.
  2. After adding const, the function can accept const and non-const parameters; if not, it can only accept non-const parameters.

Reasons for adding citations:

After adding the reference, it can effectively avoid the copying of the actual parameters when the function is called, which improves the efficiency of the program.

Notes: The above regulations are not mandatory. There can be no const or no reference, and even the parameter may not be the object where the function is located.

2.2 Return value

Under normal circumstances, the return value is the reference of the assignee, namely *this, for the following reasons:

  1. Return *this, avoiding a copy of the function and improving the efficiency of the program.
  2. Returning references can also achieve the effect of continuous assignment, such as "a = b = c". If the return type is not a reference but a return value type, then when b = c is executed, the assignment operator overload function is called. When the function returns, an unnamed temporary object will be formed, then the temporary object will be copied, and then the temporary object will be returned , But this temporary object is an rvalue, and when a = is performed again, an error will occur.

2.3 When to call

When assigning a value to a class object, the object will call the assignment operator overload function of the class.

    MyStr str1;
    str1 = str2;
    MyStr str3 = str2;

For example, in the above example, define a MyStr class. There is a difference between the second statement and the third statement in calling the function.

MyStr str1; is the declaration and definition of str1, calling the constructor without parameters, so when str2 = str1, when str1 already exists, use str2 to assign the value to str1, call the assignment operator overload function; and MyStr str3 = str2; called Is the copy constructor.

Two, assignment operator overloaded function exercise

Define a date class to implement various operator overloads:

#include<iostream>
#include <cassert>
using namespace std;

class Date
{
    
    
    friend ostream& operator<<(ostream& out,const Date &d);
    friend istream& operator>>(istream& is,Date &d);
public:
    //构造函数
    explicit Date (int year = 1900,int month = 1,int day = 1)
    {
    
    
        _year = year,_month = month,_day = day;
        //参数检测
        if ((year >= 1900) && (month >= 1 && month <= 12) && (day >= 1 && day <= Day_Of_Month(year,month)))
        {
    
    
            _year = year,_month = month,_day = day;
        }else
        {
    
    
            cout<<"日期非法"<<endl;
            _year = 1900,_month = 1,_day = 1;
        }
    }
    //拷贝构造函数
    Date (const Date& d) : _year(d._year),_month(d._month),_day(d._day)
    {
    
    }

    //析构函数
    ~Date()
    = default;


public:
    //操作符重载
    Date& operator=(const Date &d);
    bool operator==(const Date &d);
    bool operator!=(const Date &d);
    bool operator>(const Date &d);
    bool operator>=(const Date &d);
    bool operator<(const Date &d);
    bool operator<=(const Date &d);
    Date operator+(int day);
    Date& operator+=(int day);
    Date operator-(int day);
    int operator-(const Date &d); //两个日期相隔天数
    Date& operator-=(int day);
    Date& operator++();
    Date operator++(int);
    Date& operator--();
    Date operator--(int);

public:
    int Day_Of_Month(int year,int month)
    {
    
    
        //检查合法性
       assert(month > 0 && month <= 12);
       int arr[13] = {
    
    0,31,29,31,30,31,30,31,31,30,31,30,31};
       int day;
       if (!(Is_Leap_Year()) && month == 2)
        {
    
    
           _day = arr[month] - 1;
        }
        day = arr[month];
        return day;
    }

    bool Is_Leap_Year()
    {
    
    
        return (_year % 4 == 0 && _year % 100 != 0) || _year % 400 == 0 || false;
    }
private:
    int _year,_month,_day;
};

ostream& operator<<(ostream& out,const Date &d)
{
    
    
    out<<d._year<<"-"<<d._month<<"-"<<d._day<<endl;
    return out;
}

istream& operator>>(istream& is, Date &d)
{
    
    
    cout<<"输入日期:";
    is >>d._year;
    is >>d._month;
    is >>d._day;
    return is;
}

//赋值
Date& Date::operator=(const Date &d)
{
    
    
    if (*this != d)
    {
    
    
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    return *this;
}

bool Date::operator==(const Date &d)
{
    
    
    return (_year == d._year) && (_month == d._month) && (_day == d._day);
}

bool Date::operator!=(const Date &d)
{
    
    
    return !(*this == d);
}

bool Date::operator>(const Date &d)
{
    
    
    return (_year > d._year) || ((_year == d._year) && (_month > d._month)) || ((_year == d._year) && (_month == d._month) && (_day > d._day));
}

bool Date::operator>=(const Date &d)
{
    
    
    return (*this == d) || (*this > d);
}

bool Date::operator<(const Date &d)
{
    
    
    return (_year < d._year) || ((_year == d._year) && (_month < d._month)) || ((_year == d._year) && (_month == d._month) && (_day < d._day));
}

bool Date::operator<=(const Date &d)
{
    
    
    return (*this == d) || (*this < d);
}

Date& Date::operator++()
{
    
    
    if (_day > Day_Of_Month(_year,_month))
    {
    
    
        _day -= Day_Of_Month(_year,_month);
        _month++;
        if (_month > 12)
        {
    
    
            _year++;
            _month = 1;
        }
    }
    return *this;
}

Date Date::operator++(int)
{
    
    
    Date ret = *this;
    _day++;
    if (_day > Day_Of_Month(_year,_month))
    {
    
    
        _day = Day_Of_Month(_year,_month);
        _month++;
        if (_month > 12)
        {
    
    
            _year++;
            _month = 1;
        }
    }
    return ret;
}

Date& Date::operator--()
{
    
    
    _day--;
    if (_day < 1)
    {
    
    
        _month--;
        if (_month < 1)
        {
    
    
            _year--;
            _month = 12;
        }
        _day += Day_Of_Month(_year,_month);
    }
    return *this;
}

Date Date::operator--(int)
{
    
    
    Date ret = *this;
    _day--;
    if (_day < 1)
    {
    
    
        _month--;
        if (_month < 1)
        {
    
    
            _year--;
            _month = 12;
        }
        _day += Day_Of_Month(_year,_month);
    }
    return ret;
}

Date Date::operator+(int day)
{
    
    
    Date ret = *this;
    if (day < 0)
    {
    
    
        return ret - (-day);
    }
    ret._day += day;
    while (ret._day > Day_Of_Month(ret._year,ret._month))
    {
    
    
        ret._day -= Day_Of_Month(ret._year,ret._month);
        if (ret._month == 12)
        {
    
    
            ret._year++;
            ret._month = 1;
        } else{
    
    
            ret._month++;
        }
    }
    return ret;
}

Date& Date::operator+=(int day)
{
    
    
    *this  = *this + day;
    return *this;
}

Date Date::operator-(int day)
{
    
    
    Date ret = *this;
    if (day < 0)
    {
    
    
        return ret + (-day);
    }
    ret._day -= day;
    while (ret._day <= 0)
    {
    
    
        if (ret._month == 1)
        {
    
    
            ret._year--;
            ret._month = 12;
        }else{
    
    
            --ret._month;
        }
        ret._day += Day_Of_Month(ret._year,ret._month);
    }
    return ret;
}

Date& Date::operator-=(int day)
{
    
    
    *this -= day;
    return *this;
}

int Date::operator-(const Date &d)
{
    
    
    //比较两个日期的大小,找出最大的或者最小的
    Date Max = *this;
    Date Min = d;
    int flag = 1;
    if (*this < d)
    {
    
    
        Min = *this;
        Max = d;
        flag = -1;
    }
    int day = 0;
    while (Max != Min)
    {
    
    
        --Max;
        ++day;
    }
    return flag * day;
}

int main()
{
    
    
    Date d1(2021,12,31);
    Date d2(2021,3,1);
    cout<<d1;
    int ret = d1 - d2;
    cout<<ret<<endl;
    Date d3 = d1 + 332;
    cout<<d3<<endl;
    Date d4(d2);
    cout<<d4<<endl;
    Date d5 = d1 - 1;
    cout<<d5<<endl;
    Date d6 = d1++;
    cout<<d6<<endl;
    Date d7;
    cin>>d7;
    cout<<d7;
    d1 += 2;
    cout<<d1<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/xhuyang111/article/details/114918757