网站搭建多少钱徐州百都网络非常好,wordpress ciphpdown,重庆企业的网站建设,安平县外贸网站建设目录
1. 简单认识C 类的默认函数
1.1 默认构造函数
1.2 析构函数
1.3 拷贝构造函数
2. 拷贝构造函数的深入理解
拷贝构造的特点:
实际运用
3. 赋值运算符重载的深入理解
3.1.运算符重载
3.2样例
1.比较运算符重载
2.算术运算符重载
3.自增和自减运算符重载
4.输…
目录
1. 简单认识C 类的默认函数
1.1 默认构造函数
1.2 析构函数
1.3 拷贝构造函数
2. 拷贝构造函数的深入理解
拷贝构造的特点:
实际运用
3. 赋值运算符重载的深入理解
3.1.运算符重载
3.2样例
1.比较运算符重载
2.算术运算符重载
3.自增和自减运算符重载
4.输入输出运算符重载 3.3.赋值运算符重载
总结 在 C 编程中类的默认函数拷贝构造函数以及赋值运算符重载是非常重要的概念。它们不仅可以让我们更方便地操作对象还能增强代码的可读性和可维护性。本文将结合提供的日期类Date代码深入剖析这些概念。
1. 简单认识C 类的默认函数
在 C 中当我们定义一个类时编译器会自动为我们生成一些默认的成员函数包括默认构造函数、析构函数、拷贝构造函数和赋值运算符重载函数。不过当我们手动定义了其中某些函数时编译器就不会再生成对应的默认函数了。
1.1 默认构造函数
默认构造函数是在创建对象时没有提供任何参数时调用的函数。在Date类中我们手动定义了一个带参数的构造函数
Date(int year 1, int month 1, int day 1)
{_year year;_month month;_day day;
}
这个构造函数有默认参数因此它既可以作为带参数的构造函数使用也可以作为默认构造函数使用。当我们创建对象时不提供参数就会使用默认值year 1, month 1, day 1。
1.2 析构函数
析构函数在对象生命周期结束时自动调用用于释放对象占用的资源。在Date类中析构函数如下
~Date()//可不写
{_year 0;_month 0;_day 0;
}
1.3 拷贝构造函数
拷贝构造函数用于创建一个新对象该对象是另一个已存在对象的副本。在Date类中注释掉的拷贝构造函数如下
// Date(const Date d1)//可不写
// {
// _year d1._year;
// _month d1._month;
// _day d1._day;
// }
2. 拷贝构造函数的深入理解
如果一个构造函数的第一个参数是自身类类型的引用且任何额外的参数都有默认值则此构造函数也叫做拷贝构造函数也就是说拷贝构造是一个特殊的构造函数。 拷贝构造的特点: 1.拷贝构造函数是构造函数的一个重载。 2.拷贝构造函数的参数只有一个且必须是类类型对象的引用使用传值方式编译器直接报错因为语法逻辑上会引发无穷递归调用。 3.C规定自定义类型对象进行拷贝行为必须调用拷贝构造所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。 4.若未显式定义拷贝构造编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝)对自定义类型成员变量会调用他的拷贝构造。 5.像Date这样的类成员变量全是内置类型且没有指向什么资源编译器自动生成的拷贝构造就可以完成需要的拷贝所以不需要我们显示实现拷贝构造。像Stack这样的类虽然也都是内置类型但是_a指向了资源编译器自动生成的拷贝构造完成的值拷贝/浅拷贝不符合我们的需求所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部主要是自定义类型Stack成员编译器自动生成的拷贝构造会调用Stack的拷贝构造也不需要我们显示实现MyQueue的拷贝构造。这里还有一个小技巧如果一个类显示实现了析构并释放资源那么他就需要显示写拷贝构造否则就不需要。
实际运用
拷贝构造函数的原型通常为ClassName(const ClassName other)。当我们使用以下方式创建对象时会调用拷贝构造函数
Date d1(2025, 6, 12);
Date d2(d1); // 调用拷贝构造函数
在Date类中由于成员变量都是基本数据类型浅拷贝就足够了。但如果类中包含动态分配的资源如指针浅拷贝可能会导致多个对象指向同一块内存从而在析构时引发重复释放的问题这时就需要手动定义拷贝构造函数进行深拷贝。
3. 赋值运算符重载的深入理解
3.1.运算符重载
1.当运算符被用于类类型的对象时C语言允许我们通过运算符重载的形式指定新的含义。C规定类类型对象使用运算符时必须转换成调用对应运算符重载若没有对应的运算符重载则会编译报错。 2.运算符重载是具有特殊名字的函数他的名字是由operator和后面要定义的运算符共同构成。和其他函数一样它也具有其返回类型和参数列表以及函数体。 3.重载运算符函数的参数个数和该运算符作用的运算对象数量一样多。一元运算符有一个参数二元运算符有两个参数二元运算符的左侧运算对象传给第一个参数右侧运算对象传给第二个参数。 4.如果一个重载运算符函数是成员函数则它的第一个运算对象默认传给隐式的this指针因此运算符重载作为成员函数时参数比运算对象少一个。 5.运算符重载以后其优先级和结合性与对应的内置类型运算符保持一致。不能通过连接语法中没有的符号来创建新的操作符:比如operator。 6.注意以下5个运算符不能重载 7.重载操作符至少有一个类类型参数不能通过运算符重载改变内置类型对象的含义如:int operator(int xint y) 8.一个类需要重载哪些运算符是看哪些运算符重载后有意义比如Date类重载operator-就有意义但是重载operator就没有意义。
3.2样例
1.比较运算符重载
比较运算符, !, , , , 用于比较两个对象的大小关系。以运算符重载为例
bool Date::operator(const Date d) const
{return _year d._year _month d._month _day d._day;
} 这个函数比较两个Date对象的年、月、日是否相等如果相等则返回true否则返回false。其他比较运算符的重载也类似通过比较成员变量的值来确定对象的大小关系。
2.算术运算符重载
算术运算符, -, , -用于对日期进行加减操作。以运算符重载为例
Date Date::operator(int day)
{if(day 0){return *this - (-day);}_day day;while(_day GetMonthDay(_year, _month))//获取该月天数的函数{_day - GetMonthDay(_year, _month);_month;if(_month 13){_year;_month 1;}}return *this;
}
这个函数将日期加上指定的天数并处理了跨月和跨年的情况。运算符重载则是通过调用运算符重载来实现的
Date Date::operator(int day) const
{Date tmp *this;tmp day;return tmp;
}
3.自增和自减运算符重载
自增和自减运算符, --分为前置和后置两种形式。前置运算符返回引用后置运算符返回临时对象。以前置运算符重载为例
Date Date::operator()
{*this 1;return *this;
}
后置运算符重载通过一个int参数来区分前置和后置
Date Date::operator(int)
{Date tmp *this;*this 1;return tmp;
}
4.输入输出运算符重载
输入输出运算符, 用于将对象输出到流中或从流中读取对象。
ostream operator(ostream out, const Date d)
{out d._year 年 d._month 月 d._day 日 endl;return out;
} 这个函数将Date对象的年、月、日输出到输出流中。运算符重载则用于从输入流中读取年、月、日并检查输入的日期是否合法
istream operator(istream in, Date d)
{while(1){cout 请输入年月日:;in d._year d._month d._day;if(!d.CheckDate()){cout 输入的日期非法!;d.Print();cout 请重新输入年月日 endl;}else{break;}}return in;
} 3.3.赋值运算符重载
赋值运算符重载是一个默认成员函数用于完成两个已经存在的对象直接的拷贝赋值这里要注意跟拷贝构造区分拷贝构造用于一个对象拷贝初始化给另一个要创建的对象。
赋值运算符重载的特点: 1.赋值运算符重载是一个运算符重载规定必须重载为成员函数。赋值运算重载的参数建议写成const 当前类类型引用否则会传值传参会有拷贝 2.有返回值且建议写成当前类类型引用引用返回可以提高效率有返回值目的是为了支持连续值场景。 3.没有显式实现时编译器会自动生成一个默认赋值运算符重载默认赋值运算符重载行为跟默认构造函数类似对内置类型成员变量会完成值拷贝/浅拷贝(一个字节一个字节的拷贝)对自定义类型成员变量会调用他的拷贝构造。 4.像Date这样的类成员变量全是内置类型且没有指向什么资源编译器自动生成的赋值运算符重载可以完成需要的拷贝所以不需要我们显示实现赋值运算符重载。像Stack这样的类虽然也都是内置类型但是_a指向了资源编译器自动生成的赋值运算符重载完成的值拷贝/浅拷贝不符合我们的需求所以需要我们自己实现深拷贝(对指向的资源也进行拷贝)。像MyQueue这样的类型内部主要是自定义类型Stack成员编译器自动生成的赋值运算符重载会调用Stack的赋值运算符重载,也不需要我们显示实现MyQueue的赋值运算符重载。这里还有一个小技巧如果一个类显示实现了析构并释放资源那么他就需要显示写赋值运算符重载否则就不需要。
总结
通过对Date类的分析我们深入了解了 C 类的默认函数、拷贝构造函数和赋值运算符重载的概念和用法。默认函数为我们提供了基本的对象创建和销毁机制拷贝构造函数用于创建对象的副本运算符重载则让我们可以像使用内置类型一样使用自定义类型进行运算。在实际编程中我们需要根据类的具体情况来决定是否需要手动定义这些函数以确保代码的正确性和性能。