域名可以绑定几个网站,东莞网站推广软件,wordpress文章如何去除p节点,企业门户网站模板html一 类的6个默认成员函数#xff1a;
如果一个类中什么成员都没有#xff0c;简称为空类。
例#xff1a;
#include iostream
class Empty
{// 空类#xff0c;什么成员都没有
};
空类中真的什么都没有吗#xff1f;并不是#xff0c;任何类在什么都不写时
如果一个类中什么成员都没有简称为空类。
例
#include iostream
class Empty
{// 空类什么成员都没有
};
空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6个默认成员 函数。
默认构造函数如果用户没有定义任何构造函数编译器会自动生成一个默认构造函数。
拷贝构造函数用于创建一个对象是另一个对象的副本。如果用户没有定义编译器会生成一个默认的拷贝构造函数。
拷贝赋值运算符用于将一个对象赋值给另一个对象。如果用户没有定义编译器会生成一个默认的拷贝赋值运算符。
移动构造函数用于将资源从一个对象移动到另一个对象。如果用户没有定义编译器会生成一个默认的移动构造函数。
移动赋值运算符用于将资源从一个对象移动并赋值给另一个对象。如果用户没有定义编译器会生成一个默认的移动赋值运算符。
析构函数用于销毁对象并释放资源。如果用户没有定义编译器会生成一个默认的析构函数。 默认成员函数用户没有显式实现编译器会生成的成员函数称为默认成员函数。
二 构造函数
2.1构造函数的概念
构造函数是一个特殊的成员函数它的名称与类名相同没有返回值。在创建类的对象时构造函数由编译器自动调用用于初始化对象的数据成员。
2.2构造函数的特征
函数名与类名相同。
没有返回值。
在对象实例化时由编译器自动调用。
构造函数可以重载即一个类可以有多个构造函数只要它们的参数列表不同。
2.3无参/有参构造函数代码示例
class Date
{
public://有参数的构造函数//Date(int _year 1999 , int _month 2 , int _day 26)// 无参构造函数Date() //函数名与类名相同。{// 使用 this 指针访问成员变量this-_year 2024;this-_month 7;this-_day 6;}void Print(){std::cout this-_year - this-_month - this-_day std::endl;}private:int _year;int _month;int _day;
};int main()
{Date d1; //调用无参数构造函数 d1.Print();//Date d2(2022, 7, 6); //调用带参构造函数//d2.Print();return 0;
}
Date()是无参的构造函数没有参数。在对象 d1 创建时自动调用。你们有可能会问了为什么在无参的构造函数里面this指针指向成员变量那为什么main函数里见不到this指针呢因为当 Date d1; 创建对象时编译器会自动传递 d1 的地址给 this 指针所以就不需要显示this指针。
如果类中没有显式定义构造函数编译器会自动生成一个无参的默认构造函数。一旦用户显式定义了任何构造函数编译器将不再生成无参的默认构造函数。
2.4默认构造函数代码示例
class Date
{
public:void Print() {std::cout _year - _month - _day std::endl;}private:int _year;int _month;int _day;
};int main()
{Date d1;d1.Print();return 0;
}
输出 上面代码因我未显示定义构造函数所以编译器帮我生成了一个默认的构造函数而且是看不见的那为什么默认生成的输出的值是随机值呢
原来C把类型分为内置类型和自定义类型内置类型就是语言提供的基本数据类型如int、char等。自定义类型是用户定义的类型如使用class、struct、union定义的类型。
2.5内置类型和自定义类型的默认构造函数处理
内置类型 1.内置类型的成员变量在默认构造函数中不会被自动初始化 2.如果不显式初始化成员变量的值将是未定义的即随机值
自定义类型 1.自定义类型的成员变量在默认构造函数中会调用其默认构造函数。 这意味着即使你没有显式定义自定义类型的构造函数编译器也会自动调用默认构造函数来 初始化这些成员变量。
例子
class Time
{
public:Time() {// Time类的无参构造函数std::cout Time() std::endl;_hour 0;_minute 0;_second 0;}private:int _hour;int _minute;int _second;
};class Date
{
public:Date()// 初始化内置类型成员变量{this-_year 2024;this-_month 7;this-_day 5;}void Print(){std::cout _year - _month - _day std::endl;}private:int _year; // 内置类型int _month; // 内置类型int _day; // 内置类型Time _t; // 自定义类型
};int main()
{Date d; // 调用无参构造函数d.Print();return 0;
}输出 我们来说一下它的执行顺序首先是执行主函数main当执行到 Date d; 时编译器就会先去调用自定义函数Time_t;然后等它全部初始化完成 再去调用无参数构造并且初始化里面的内置类型。
那我们这是显式定义自定义类型的构造函数并且给成员变量赋值了所以就不会出现随机值如果想要显式定义自定义类型的构造函数并且不想要随机值那该怎么办呢这时候C11 中针对内置类型成员不初始化的缺陷又打了补丁即内置类型成员变量在类中声明时可以给默认值。
例子
class Date
{
public:void Print(){std::cout _year - _month - _day std::endl;}private:int _year 2024; // 内置类型int _month 2; // 内置类型int _day 1; // 内置类型
};
输出 2.6默认构造函数
在C中默认构造函数是指在创建对象时不需要提供任何参数的构造函数。默认构造函数可以分为两种
默认构造函数一个类只能有一个真正的默认构造函数不需要参数。无参构造函数和全缺省参数构造函数 如果参数不同它们会重载编译器不会报错。如果参数相同即都没有参数它们就相当于有两个默认构造函数这时编译器会报错因为无法区分调用哪个构造函数。
关键点
无参构造函数没有参数的构造函数。 全缺省参数构造函数所有参数都有默认值的构造函数。 重载当构造函数的参数列表不同它们可以共存且不会冲突。 例子
class Date
{
public:// 无参构造函数Date() {_year 2024;_month 7;_day 2;}// 全缺省参数构造函数Date(int year 2023, int month 1, int day 1) {_year year;_month month;_day day;}void Print(){std::cout _year - _month - _day std::endl;}private:int _year;int _month;int _day;
};int main()
{Date d; // 调用无参构造函数d.Print();Date d2(2023, 4, 3); // 调用全缺省参数构造函数d2.Print(); return 0;
}输出 之所以会报错是因为全缺省参数构造函数和无参数构造函数它们都有自己的默认值当执行到Date d; 时它并不知道到底要调用哪一个所以就会报错那怎么更改呢只需要把全缺省参数的默认值给去掉就行了这样编译器就不会迷糊到底要调用哪一个了
三 析构函数
3.1 析构函数的概念
通过前面构造函数的学习我们知道一个对象是怎么来的那一个对象又是怎么没呢的 析构函数与构造函数功能相反析构函数不是完成对对象本身的销毁局部对象销毁工作是由 编译器完成的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作。
3.2 析构函数的特征
1名称析构函数的名称是在类名之前加上~。
2无参数无返回值析构函数没有参数也没有返回值。
3唯一性每个类只能有一个析构函数。
4自动调用当对象的生命周期结束时析构函数会被编译器自动调用。
5不可重载析构函数不能像其他成员函数一样被重载。
3.3代码示例 class Time
{
public:Time() {std::cout Time() std::endl;_hour 0;_minute 0;_second 0;}~Time() {std::cout ~Time() std::endl;}private:int _hour;int _minute;int _second;
};class Date
{
public:Date() {std::cout Date() std::endl;_year 2024;_month 7;_day 2;}Date(int year, int month, int day) {_year year;_month month;_day day;}~Date() {std::cout ~Date() std::endl;}void Print(){std::cout _year - _month - _day std::endl;}private:int _year;int _month;int _day;Time _t; // 自定义类型成员变量
};int main()
{Date d1; // 创建Date对象调用Date构造函数和Time构造函数d1.Print();Date d2(2023, 4, 3);d2.Print();return 0;
}
输出 我们现在来捋一下它的执行过程
首先从主函数进入之后就会执行无参的构造函数但因无参构造函数里有自定义类型成员变量所以先要调用Time(); 你们是不是调用完它之后直接就跳动析构函数这是不被允许的 原因是析构函数要等对象的生命周期结束时析构函数会被编译器自动调用,自定义类型成员变量执行完了那就该执行无参构造函数了然后就这样循环直到程序结束的时候就会调用d1和d2的析构函数先调用Date的析构函数再调用Time的析构函数。
根据上面析构输出的打印那咱们想没想过为什么是先调用Date然后再调用Time呢跟上面的无参数构造函数的输出截然不同这是什么原因呢
3.4 构造函数和析构函数的调用顺序
构造函数调用顺序
1. 首先调用成员变量的构造函数
2. 然后调用包含这些成员变量的类的构造函数。
析构函数调用
1. 首先调用包含这些成员变量的类的析构函数。
2. 然后调用成员变量的析构函数。