网站系统设计,网站建设边框,用ps怎么做短视频网站,永兴做网站构造函数中可以添加参数并添加默认值构成缺省构造#xff0c;如果我们在构造函数的参数中加上自身类型类的引用和其他给出默认值的参数则会构成一种特殊的构造函数叫做———拷贝构造函数
1.拷贝构造
拷贝构造的特点#xff1a;
1.拷贝构造函数是构造函数的一个重载
2.拷…构造函数中可以添加参数并添加默认值构成缺省构造如果我们在构造函数的参数中加上自身类型类的引用和其他给出默认值的参数则会构成一种特殊的构造函数叫做———拷贝构造函数
1.拷贝构造
拷贝构造的特点
1.拷贝构造函数是构造函数的一个重载
2.拷贝构造函数的参数只有⼀个且必须是类类型对象的引用使用传值方式编译器直接报错因为语法逻辑上会引发无穷递归调用 3.C规定自定义类型对象进行拷贝行为必须调用拷贝构造所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成 4.若未显式定义拷贝构造编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝)对自定义类型成员变量会调用他的拷贝构造
5.像Date这样的类成员变量全是内置类型且没有指向什么资源编译器自动生成的拷贝构造就可以完成需要的拷贝所以不需要我们显示实现拷贝构造。像Stack栈这样的类虽然也都是内置类型但是其对象指向了资源编译器自动生成的拷贝构造完成的值拷贝/浅拷贝不符合我们的需求所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue(两个栈实现的队列)这样的类型内部主要是自定义类型Stack成员编译器自动生成的拷贝构造会调用Stack的拷贝构造也不需要我们显示实现 MyQueue的拷贝构造。这里还有⼀个小技巧如果一个类显示实现了析构并释放资源那么他就 需要显示写拷贝构造否则就不需要
6.传值返回会产生一个临时对象调用拷贝构造传值引用返回返回的是返回对象的别名(引用)没 有产生拷贝。但是如果返回对象是一个当前函数局部域的局部对象函数结束就销毁了那么使用引用返回是有问题的这时的引用相当于一个野引用类似一个野指针一样。传引用返回可以减少拷贝但是一定要确保返回对象在当前函数结束后还在才能用引用返回
例
#includeiostream
using namespace std;
class Date
{
public:Date(int year 2024, int month 11, int day 22){_year year;_month month;_day day;}Date(Date d){_year d._year;_month d._month;_day d._day;}
private:int _year;int _month;int _day;
};
Date test()
{Date d2(2024, 11, 21);return d2;//d2的作用域只在这个函数里出了这个函数后就会销毁
}
int main()
{Date d1;Date d3 test();return 0;
}
在调试此程序时我们可以通过监视窗口看到以下内容 我们可以看到d3的值是随机值说明d2并没有被返回
2.运算符重载
(1)运算符重载
1.当运算符被用于类类型的对象时C语言允许我们通过运算符重载的形式指定新的含义。C规定类类型对象使用运算符时必须转换成调用对应运算符重载若没有对应的运算符重载则会编译报错
2.运算符重载是具有特名字的函数他的名字是由operator和后面要定义的运算符共同构成。和其他函数一样它也具有其返回类型和参数列表以及函数体
代码1
#includeiostream
using namespace std;
class Date
{
public:void Print(){cout _year _month _day endl;}int GetMonthDay(int year, int month);// 全缺省的构造函数Date(int year 1900, int month 1, int day 1);// 拷贝构造函数// d2(d1)Date(const Date d){_year d._year;_month d._month;_day d._day;}// 赋值运算符重载//d2 d3 - d2.operator(d2, d3)Date operator(const Date d);// 析构函数~Date();// 日期天数Date operator(int day);// 日期天数Date operator(int day);// 日期-天数Date operator-(int day);// 日期-天数Date operator-(int day);// 前置Date operator();// 后置Date operator(int);// 后置--Date operator--(int);// 前置--Date operator--();// 运算符重载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);// 日期-日期 返回天数int operator-(const Date d);
private:int _year;int _month;int _day;
};3.重载运算符函数的参数个数和该运算符作用的运算对象数量一样多。一元运算符有一个参数二元运算符有两个参数二元运算符的左侧运算对象传给第一个参数右侧运算对象传给第二个参数
4.如果一个重载运算符函数是成员函数则它的第一个运算对象默认传给隐式的this指针因此运算符重载作为成员函数时参数比运算对象少一个
例如在代码1中我们的Date日期类中重载运算符函数是它的成员函数他的参数中是有this指针为第一个参数的所以在构建重载运算符函数时需注意参数数量
5.运算符重载以后其优先级和结合性与对应的内置类型运算符保持⼀致——即你构建的重载运算符和正常的为相等优先级和结合性
6.不能通过连接语法中没有的符号来创建新的操作符比如operator。
7. .* :: sizeof ? : . 注意以上5个运算符不能重载
8.重载操作符至少有一个类类型参数不能通过运算符重载改变内置类型对象的含义——防止你把正常的加改成减
9.⼀个类需要重载哪些运算符是看哪些运算符重载后有意义比如代码1中的Date类重载operator-就有意 义但是重载operator就没有意义
10.重载运算符时有前置和后置运算符重载函数名都是operator无法很好的区分。 C规定后置重载时增加⼀个int形参跟前置构成函数重载方便区分
11.重载和时需要重载为全局函数因为重载为成员函数this指针默认抢占了第⼀个形参位置第⼀个形参位置是左侧运算对象调用时就变成了对象cout不符合使⽤习惯和可读性。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了第二个形参位置当类类型对象
流插入
ostream operator(ostream out, const Date d)
{out d._year 年 d._month 月 d._day 日 endl;return out;
}
流提取
istream operator(istream in, Date d)
{while (1){cout 请依次输入年月日:;in d._year d._month d._day;if (d.CheckDate()){break;}else{cout 输入的日期非法请重新输入 endl;}}return in;
} (2)赋值运算符重载
赋值运算符重载是一个默认成员函数用于完成两个已经存在的对象直接的拷贝赋值这里要注意跟拷贝构造区分拷贝构造用于一个对象拷贝初始化给另一个要创建的对象
1.赋值运算符重载是一个运算符重载规定必须重载为成员函数。赋值运算重载的参数建议写成 const当前类类型引用否则会传值传参会有拷贝
class Date
{
public:Date(int year2024,int month 11,int day22){_yearyear;_monthmonth;_dayday;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2024,11,22);Date d2(2024,11,21);d1d2;//赋值运算符重载Date d3d2;//拷贝构造return 0;
} 2.有返回值且建议写成当前类类型引用引用返回可以提高效率有返回值目的是为了支持连续赋值场景
3.没有显式实现时编译器会自动生成⼀个默认赋值运算符重载默认赋值运算符重载行为跟默认构造函数类似对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝)对自定义类型成员变量会调用他的拷贝构造
4.像Date这样的类成员变量全是内置类型且没有指向什么资源编译器自动生成的赋值运算符重载就可以完成需要的拷贝所以不需要我们显示实现赋值运算符重载。像Stack这样的类虽然也都是内置类型但是指向了资源编译器自动生成的赋值运算符重载完成的值拷贝/浅拷贝不符合我 们的需求所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部 主要是自定义类型Stack成员编译器自动生成的赋值运算符重载会调用Stack的赋值运算符重载 也不需要我们显示实现MyQueue的赋值运算符重载。这里还有一个小技巧如果一个类显示实现了析构并释放资源那么他就需要显示写赋值运算符重载否则就不需要