C++拷贝构造函数和运算符重载--3 https://developer.aliyun.com/article/1424591
(3)“ 前置++,后置++,前置--,后置-- ”在类对象内定义进行演示和解说。
// 后置++,形参为int,C++专门规定,为了与前置++区分 Date operator++(int) { Date ret(*this); *this += 1; return ret; } // 前置++ Date& operator++() { *this += 1; return *this; } // 后置--,形参为int,C++专门规定,为了与前置--区分 Date operator--(int) { //先将原本类进行拷贝,然后将此对象里的值--,返回此对象,实现了先赋值,再-- Date ret(*this); *this -= 1; return ret; } // 前置-- Date& operator--() { //直接返回*this,实现了先把对象的值--,然后将此对象返回,实现了先--,再赋值 *this -= 1; return *this; }
这里要注意的是前置++、前置--和后置++、后置--的写法和前置和后置的实现。如上代码中C++的专门规定前置与后置的写法,前置的实现是先进行运算,然后再进行赋值,所以要直接用this进行。后置的实现要先进行赋值,然后再运算。这里我们虽然实现了this的运算,但返回的是运算前的对象,进而实现了此原理。
(4)赋值运算符。赋值运算符比较特殊,我们要区分它与拷贝构造。当类与类进行赋值时,若类还没有进行初始化,将会调用拷贝构造;若已进行了初始化,将会调用赋值运算符。
1,赋值运算符一般也要设置返回类型,一般返回 *this,因为我们要保证连续赋值的情况。
#include <iostream> #include <assert.h> using namespace std; class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } // 赋值运算符重载 Date& operator=(const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } private: int _year; int _month; int _day; }; int main() { Date d1(2023, 11, 9); Date d2, d3, d4; d4 = d3 = d2 = d1;//调用赋值运算符重载 return 0; }
2,赋值运算符只能重载成类的成员函数不能重载成全局函数。
class Date { public: Date(int year = 1900, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } int _year; int _month; int _day; }; // 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数 Date& operator=(Date& left, const Date& right)//出现错误,出现在全局中 { left._year = right._year; left._month = right._month; left._day = right._day; return left; }
原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现 一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,因此,赋值运算符重载只能是类的成员函数。
3,用户自己如果没有定义赋值运算符,编译器会生成一个默认赋值运算符重载,以浅拷贝的形式实现拷贝。内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。
#include <iostream> using namespace std; class Time { public: Time() { _hour = 1; _minute = 1; _second = 1; } Time& operator=(const Time& t) { _hour = t._hour; _minute = t._minute; _second = t._second; return *this; } private: int _hour; int _minute; int _second; }; class Date { private: // 基本类型(内置类型) int _year = 1970; int _month = 1; int _day = 1; // 自定义类型 Time _t; }; int main() { Date d1; Date d2; d1 = d2; return 0; }
d1 = d2运行的调试解图
默认赋值运算符重载的原理跟默认拷贝构造一样,如果类中未涉及到资源空间的管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必须要自己定义实现。
(5)流操作符的重载。在C++程序中,我们也可实现插入操作符(<<)和提取操作符(>>)的重载。
我们首先要认识ostream和istream。ostream用于处理输出流的类,类中定义了插入操作符(<<)来将数据写入输出流;istream是用于处理输入流的类。它定义了提取操作符(>>)来从输入流中提取数据。
定义样例:
在类的内部定义
第一个参数默认this指针 class Date { private: int _year = 2023; int _month = 10; int _day = 16; }; //没有返回类型的情况 void operator<<(ostream& out); void operator>>(istream& in); //在类内部声明,在外部进行定义,也相当于在内部定义 void Date::operator<<(ostream& out); void Date::operator>>(istream& in); //返回类型为ostream和istream,这种情况为了支持连续输入输出的情况,因为连续输入输出需要有返回值去接收 ostream& operator<<(ostream& out); istream& operator>>(istream& in);
在类的外部定义
没有默认参数,需要把类写入形参中 class Date { private: int _year = 2023; int _month = 10; int _day = 16; }; //没有返回类型的情况 void operator<<(ostream& out, const Date& d1); void operator>>(istream& out, const Date& d1); //返回类型为ostream和istream,这种情况为了支持连续输入输出的情况,因为连续输入输出需要有返回值去接收 ostream& operator<<(ostream& out, const Date& d1); istream& operator>>(istream& out, const Date& d1);
C++拷贝构造函数和运算符重载--5https://developer.aliyun.com/article/1424609?spm=a2c6h.13148508.setting.28.214f4f0emw3QR7