仿阿里云网站,怎么做网页机器人,做景区网站建设的公司,html5手机网站返回顶部这篇文章的主要内容是类的默认成员函数。如果对大家有用的话#xff0c;希望大家三连支持#xff0c;博主会继续努力#xff01; 目录 一.类的默认成员函数
二.构造函数
三.析构函数
四.拷贝构造函数
五.运算符重载 一.类的默认成员函数 如果一个类中什么成员都没有希望大家三连支持博主会继续努力 目录 一.类的默认成员函数
二.构造函数
三.析构函数
四.拷贝构造函数
五.运算符重载 一.类的默认成员函数 如果一个类中什么成员都没有简称为空类。空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6 个默认成员函数。 默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数。 二.构造函数 定义构造函数 是一个 特殊的成员函数名字与类名相同 , 创建类类型对象时由编译器自动调用 以保证每个数据成员都有一个合适的初始值并且在对象整个生命周期内只调用一次。 特性 1. 函数名与类名相同。 2. 无返回值。 3. 对象实例化时编译器 自动调用 对应的构造函数。 4. 构造函数可以重载。 5. 如果类中没有显式定义构造函数则 C 编译器会自动生成一个无参的默认构造函数一旦用户显式定义编译器将不再生成。 6. 编译器生成的默认构造函数对内置类型不会处理但会调用自定义类型的默认构造函数。 7. 无参的构造函数和全缺省的构造函数都称为默认构造函数并且默认构造函数只能有一个。 注意无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数都可以认为是默认构造函数。 延伸总结
三.析构函数
定义对象在销毁时会自动调用析构函数完成对象中资源的清理工作。 特征 1. 析构函数名是在类名前加上字符 ~。 2. 无参数无返回值类型。 3. 一个类只能有一个析构函数。若未显式定义系统会自动生成默认的析构函数。注意析构函数不能重载。 4. 对象生命周期结束时 C 编译系统系统自动调用析构函数。 5. 编译器生成的默认析构函数对自定义类型成员调用它的析构函数。对内置类型不做处理。内置类型出栈帧自动销毁。 6. 如果类中没有申请资源时析构函数可以不写直接使用编译器生成的默认析构函数比如Date类有资源申请时一定要写否则会造成资源泄漏比如 Stack 类。 延伸总结析构函数的作用就是在对象生命周期结束时 释放对象内手动申请的资源空间只不过自动调用比C语言方便。析构函数的调用顺序类似栈这种数据结构后创建先析构。 四.拷贝构造函数
拷贝构造函数只有单个形参该形参是对本类类型对象的引用(一般常用const修饰)在用已存在的类类型对象创建新对象时由编译器自动调用。(传值拷贝自动调用)
特性
1. 拷贝构造函数是构造函数的一个重载形式。 2. 拷贝构造函数的 参数只有一个 且 必须是类类型对象的引用 使用 传值方式编译器直接报错 因为会引发无穷递归调用。 3. 若未显式定义编译器会生成默认的拷贝构造函数。默认拷贝构造内置类型是按照字节方式直接浅拷贝。对自定义类型会调用自定义类型的拷贝构造函数。 4. 类中如果没有涉及资源申请时拷贝构造函数是否写都可以一旦涉及到资源申请 时则拷贝构造函数是一定要写的否则就是浅拷贝。 5. 拷贝构造函数典型调用场景使用已存在对象创建新对象函数参数类型为类类型对象函数返回值类型为类类型对象。 延伸总结自定义类型传值传参必须调用拷贝构造。默认拷贝构造对内置类型浅拷贝(有malloc的空间需要手动写拷贝构造没有就不用写)自定义类型调用自定义类型的拷贝构造。 在如下场景 #includeiostream
using namespace std;
class Stack
{
public:Stack(int N0)//构造函数{arr (int*)malloc(sizeof(int) * N);top capcity 0;}~Stack()//析构函数{free(arr);arr nullptr;top capcity 0;}
private:int* arr;int top;int capcity;
};
int main()
{Stack s1(4);Stack s2 s1;//传值拷贝return 0;
} 使用传值拷贝但栈类有资源申请(malloc)但没写拷贝构造系统默认拷贝构造只会对内置类型浅拷贝s1和s2的arr值就相同指向同一块堆空间。这就是默认拷贝构造的浅拷贝。 当程序结束时先自动调用s2的析构函数将arr指向的堆空间释放再调用s1的析构函数arr指向的堆空间再次释放访问了野指针程序就会崩溃。所以有资源申请的类一定要写拷贝构造函数否则在程序结束时会调用两次析构函数free两次同一块堆空间程序崩溃。 要解决上述问题需要手写拷贝构造函数完成深拷贝 Stack(Stack s)
{s.arr (int*)malloc(sizeof(int) * capcity);s.capcity capcity;s.top top;
} 五.运算符重载 C 为了增强代码的可读性引入了运算符重载 运算符重载是具有特殊函数名的函数 也具有其返回值类型函数名字以及参数列表其返回值类型与参数列表与普通的函数类似。 运算符重载函数 返回类型 operator 要重载的操作符(参数列表) 注意 1.不能通过连接其他符号来创建新的操作符比如operator 2.重载操作符必须有一个类类型参数。 3.用于内置类型的运算符其含义不能改变例如内置的整型 不 能改变其含义。 4.作为类成员函数重载时其形参看起来比操作数数目少1 因为成员函数的第一个参数为隐藏的this指针。 5. .* :: sizeof ?: . 注意以上5 个运算符不能重载。 接下来举例示范一下比较运算符重载和赋值运算符重载。 如下代码
#includeiostream
using namespace std;
class Date
{
private:int _year;int _month;int _day;
public:Date(int year 1, int month 1, int day 1)//构造函数{_year year;_month month;_day day;}};
int main()
{Date d1(2022, 9, 24);Date d2(2022, 3, 27);if (d1 d2){cout d1这个日期更大 endl;}return 0;
}
这里会编译错误因为d1,d2两个对象无法用号比较大小肉眼可见d1更大。那么如何比较大小呢
我们可以在类中定义函数
bool compare(Date d){if (_year d._year){return true;}else if (_year d._year _month d._month){return true;}else if (_year d._year _month d._month _day d._day){return true;}elsereturn false;}
通过
d1.compare(d2)true;//判断出d1大
但是这中方法代码的可读性差不能直观感受出d1,d2的大小。
C的运算符重载就应运而生了。在类中定义函数
bool operator(Date d){if (_year d._year){return true;}else if (_year d._year _month d._month){return true;}else if (_year d._year _month d._month _day d._day){return true;}elsereturn false;}
通过运算符重载以下表达式就能表达出d1大于d2
d1d2;//等价于d1.operator(d2) 这种方式大大增强了代码的可读性。