bosthhe1 / cpushpush

0 stars 0 forks source link

赋值符重载和运算符重载 #6

Open bosthhe1 opened 1 year ago

bosthhe1 commented 1 year ago

赋值符重载听起来好像是对符号重新定义一个功能,但是本质还是不变,是对已经存在的变量,进行赋值,假如a,b变量已经存在,a = b就是对a变量的赋值,在我们常规的理解中a可能是int类型,或者char类型,不可能对类进行赋值相等,赋值符重载就是为了解决这个问题,让两个类里面的成员也能相等, 这里就需要用到函数operator image 首先这里的赋值的类型视情况而定,图片里面是赋值的类的类型,所以返回类型是类,然后这里的返回值可以传引用也可以不传引用,因为传引用返回可以减少拷贝,但是有可能出了作用域参数就销毁了,所以需要确保参数不被销毁,才可以传引用。 这里的参数类型可以传引用,减少调用拷贝消耗,但是传引用有一个不安全的点,就是传了引用过来,引用就是实参的别名,我们改变函数的参数,就改变了外面的实参,所以我们一般在前面会加一个const image 同样我们这里会有一个this指针 注意我们需要将赋值符重载和拷贝构造函数区分开 赋值符重载是将两个已经存在的变量,进行操作 拷贝构造函数重载是将一个已经存在的变量,去初始化另外一个未初始化的变量

bosthhe1 commented 1 year ago
#include<iostream>
using namespace std;
class DATE
{
public:
    DATE(int year = 1970,int monsh = 1,int day = 1)
    {
        _year = year;
        _monsh = monsh;
        _day = day;
    }
    DATE(DATE &d)
    {
        _year = d._year;
        _monsh = d._monsh;
        _day = d._day;
    }
    DATE& operator=(const DATE &d);
    bool operator!=(const DATE &d)const;
    bool operator>(const DATE &d)const;
    bool operator==(const DATE &d)const;
    bool operator>=(const DATE &d)const;
    bool operator<=(const DATE &d)const;
    bool operator<(const DATE &d)const;
    int GetMonshDay(int year, int monsh);
    friend ostream& operator<<( ostream &cout,const DATE& d);
    friend istream& operator>>(istream &cin,DATE& d);
    int operator-(DATE& d);
    DATE& operator++();
    DATE operator+(int day);
    void Print() const;
private:
    int _year =10;
    int _monsh=20;
    int _day;   
};
DATE DATE::operator+(int day)
{
    DATE tmp(*this);
    tmp._day+=day;
    while(tmp._day > GetMonshDay(tmp._year,tmp. _monsh))
    {
        tmp._day -= GetMonshDay(tmp._year,tmp._monsh);
        tmp._monsh++;
        if (tmp._monsh > 12)
        {
            tmp._year++;
            tmp._monsh = 1;
        }
    }
    return tmp;
}
bool DATE::operator!=(const DATE &d)const
{
    if (_year != d._year)
        return false;
    if (_year == d._year&&_monsh != d._monsh)
        return false;
    if (_year == d._year&&_monsh == d._monsh&&_day != d._day)
        return false;
    return true;
}
DATE& DATE::operator++()
{
    _day++;
    if (_day++ > GetMonshDay(_year, _monsh))
    {
        _day -= GetMonshDay(_year, _monsh);
        _monsh++;
        if (_monsh > 12)
        {
            _year++;
            _monsh = 1;
        }
    }
    return *this;
}

int DATE::operator-(DATE& d)
{
    int flag = 1;
    DATE min = (*this);
    DATE max = d;
    if (max > min)
    {
        flag = 1;
    }
    else
    {
        max = (*this);
        min = d;
        flag = -1;
    }
    int day = 0;
    while ((min+day) < max)
    {
        day++;
    }
    return day*flag;
}
istream& operator>>(istream &cin,DATE& d)
{
    cin >> d._year >>d._monsh >>d._day;
    return cin;
}
ostream& operator<<(ostream &cout,const DATE& d)
{
    cout << d._year << "-" << d._monsh << "-" << d._day<<endl ;
    return cout;
}
void DATE::Print()const
{
    cout << _year << "-" << _monsh << "-" << _day << endl;
}

bool DATE::operator==(const DATE &d)const
{
    if (_year == d._year&&_monsh == d._monsh&&_day == d._day)
    {
        return true;
    }
    return false;
}
int DATE::GetMonshDay(int year,int monsh)
{
    int GetMonshArr[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
    {
        GetMonshArr[2]++;
    }
    return GetMonshArr[monsh];
}

bool DATE::operator>(const DATE &d)const
{
    if (_year > d._year)
    {
        return true;
    }
    if (_year == d._year&&_monsh > d._monsh)
    {
        return true;
    }
    if (_year == d._year&&_monsh == d._monsh&&_day > d._day)
    {
        return true;
    }
    return false;
}
bool DATE::operator>=(const DATE &d)const
{
    if (*this > d || *this == d)
    {
        return true;
    }
    return false;
}
bool DATE::operator<(const DATE &d)const
{
    if (!(*this>d))
        return true;
    return false;
}
bool DATE::operator<=(const DATE &d)const
{
    if (*this < d || *this == d)
    {
        return true;
    }
    return false;
}

DATE& DATE::operator=(const DATE &d)
{
    _year = d._year;
    _monsh = d._monsh;
    _day = d._day;
    return *this;
}
int main()
{

    DATE d1;
    DATE d2(1998,12,03);
    cout << ++d1 << ++d2;
    //cin >> d2 >> d1;
    //cout << d2;
    //cout << d1;
    //cout << (d1 - d2) << endl;
    //cout << (d2 > d1) << endl;
    //cout << (d2 <= d1) << endl;
    DATE const d3;
    d3.Print();
    return 0;
}
bosthhe1 commented 1 year ago

初始化列表的注意事项 image

bosthhe1 commented 1 year ago

上面的初始化列表按照顺序走的话,是先将1给了_a1赋值,然后将_a1给_a2赋值,这样打印出来a1和a2都是1,但是实际上却不是这个逻辑 image 我们看到a1是1,但是a2是随机值,因为初始化列表初始化的顺序是按照成员声明的顺序走的,我们先声明了a2,然后再声明了a1,所以初始化列表会先初始化a2,再初始化a1,a2的初始化是靠a1的值,但是a1还未被初始化,所以是随机值,那么我们看到的a2打印出来就是随机值,而a1不受影响

bosthhe1 commented 1 year ago

需要注意的是,我们对于const函数和普通函数调用是不一样的,const的函数调用,是需要调用对象的本身是const才可以调用,而普通函数则没有影响,函数调用和接受值无关,编译器不会用这里的iterator去推到调用的函数,而是用对象本身是否拥有const属性来调用具体函数 类型匹配(会去调用最匹配的问题): 普通对象,如果存在普通的函数和const函数,就会去调用普通函数(权限不变),如果没有普通函数,只有const函数,就去调用const的函数(权限缩小),但是对于const对象,就只能调用const的函数,不能调用普通函数,如果没有const函数会报错 image image 我们看到在函数调用的时候,都是调用的begin(),但是it是调用的普通函数,it2是调用const修饰的函数

bosthhe1 commented 1 year ago

需要注意的是,前置++和后置++,编译器为了区分前置++和后置++,将后置++进行运算符重载,使用了占位参数,这个占位参数类型必须是int DATE operator++();前置++ DATE operator++(int);后置++,占位参数必须是int

bosthhe1 commented 1 year ago

赋值运算符只能重载成成员函数,在类中不显式实现时,编译器会生成一份默认的,此时用户在类外再将赋值运算符重载为全局的,就和编译器生成的默认赋值运算符冲突了,故赋值运算符只能重载成成员函数