企业网站怎么查,一般哪些商家需要建设网站,河南郑州创建网站公司,北京建设网站目录
1.类的6个默认成员函数
2.构造函数
2.1概念
2.2特性
3.析构函数
3.1析构函数的概念
3.2特性 1.类的6个默认成员函数 如果一个类中什么成员都没有#xff0c;简称为空类。 空类中真的什么都没有吗#xff1f;并不是#xff0c;任何类在什么都不写时#xff0c;…目录
1.类的6个默认成员函数
2.构造函数
2.1概念
2.2特性
3.析构函数
3.1析构函数的概念
3.2特性 1.类的6个默认成员函数 如果一个类中什么成员都没有简称为空类。 空类中真的什么都没有吗并不是任何类在什么都不写时编译器会自动生成以下6个默认成员 函数。 默认成员函数 用户没有显式实现编译器会生成的成员函数称为默认成员函数。 下面我们来分别学习一下这6个函数~
2.构造函数
2.1概念
class Date
{
public:void Init(int year, int month, int day){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}
在日常使用时我们可能会忘记对对象进行初始化程序报错后反而检查半天才发现问题。在为了避免这种失误出现C中引入了构造函数。 构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用以保证每个数据成员都有一个合适的初始值并且在对象整个生命周期内只调用一次。 2.2特性
构造函数在函数名上看起来好像是创建对象实际上是完成对象的初始化。
构造函数特征如下
①函数名和类名相同
②没有返回值不是在前加void而是压根不需要写
③对象实例化时编译器自动调用对应的构造函数
④构造函数可以重载
上面代码的构造函数形式如下
1不带参数的构造函数由于编译器自动调用构造函数在定义对象时就已经初始化了 2带参数的构造函数在定义对象的时候就要将初始化的值加在后面。 调用带参的构造函数时在括号内加入要初始化的值跟在对象后那调用无参的构造函数时可以直接跟括号在对象后吗为什么调用无参的构造函数时后面不用加括号 不能。这种形式就成了函数声明。 如下图声明了一个d3函数该函数没有参数返回一个Date类型对象。 以理论上两种形式可以同时存在构成了函数重载但是一般情况下我们不会同时写出这两个因为调用存在歧义。
这两种形式可以合为一种利用我们之前学过的缺省参数来修改如下面图中的形式 ⑤如果在类中忘记显式定义构造函数也不用担心C编译器会自动生成一个无参的默认构造函数。 我们忘记定义构造函数时执行程序发现可以正常运行这是因为编译器会自动生成一个默认构造函数但是看运行结果截图我们可以发现编译器没有对参数进行初始化_year、_month、_day都是随机值。那么编译器生成的默认构造函数有什么用呢 C中把类型分成内置类型基本类型和自定义类型。内置类型就是语言提供的数据类型像int/char/double/指针等自定义类型就是我们使用的struct、class等自己定义的类型。 C98中规定对默认生成的构造函数对内置类型不作处理对自定义类型则调用它的默认构造函数。如果自定义类型没有默认构造函数就会报错。 其实自定义类型的尽头就是内置类型。 以上Date类中的_year、_month、_day就是int类型所以不作处理是随机值接下来我们验证一下自定义类型。 •有些编译器可能会对内置类型进行处理int初始化为0double初始化为0.0指针初始化为nullptr但C标准并没有规定内置类型要处理。
C11中对内置类型不处理的缺陷又打了补丁即内置类型成员变量在类中声明时可以给默认值。 分析一个类型成员和初始化要求如果需要些构造函数我们就自己写不需要时就靠编译器自动生成。结论大多情况下都需要自己实现构造函数。 ⑥无参的构造函数和全缺省的构造函数都称为默认构造函数并且默认构造函数只能有一个。 注意无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数都可以认为 是默认构造函数。 不止是编译器生成的构造函数叫默认构造函数我们自己显式定义的无参构造函数全缺省构造函数都是默认构造函数。即不需要传参就能调用的构造函数就叫默认构造函数。 默认生成的构造函数不能与其他两种同时存在无参构造函数不能与全缺省构造函数同时存在会产生调用歧义。 一般情况下我们建议使用全缺省构造函数。 3.析构函数
3.1析构函数的概念
前面我们学习了对对象进行初始化的构造函数类似于栈中的初始化函数Init那么怎样清理资源呢这就要提到我们接下来要学习的析构函数栈中的销毁函数Destory。
析构函数也是一种特殊的成员函数与构造函数功能相反析构函数不是完成对对象本身的销毁局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数完成对象中资源的清理工作。
3.2特性
析构函数特征 ①析构函数名是在类名前加上字符 ~。C语言中“~”作用是按位取反析构函数前加表示该函数与构造函数作用相反 ②无参数无返回值类型。 ③一个类只能有一个析构函数。若未显式定义系统会自动生成默认的析构函数。注意析构 函数不能重载 默认生成的析构函数与构造函数类似对内置类型不作处理自定义类型则调用它的析构函数。 Date类没有显式定义析构函数系统将自动生成Date类中定义了自定义类型Time类型的对象t调用它的析构函数~Time()。 ④对象生命周期结束时C编译系统系统自动调用析构函数。 以下面的日期类为例定义一个析构函数~Date()。其实日期类的析构函数没什么有用的因为它的_year等都是属于对象并没有额外开辟空间也就没有什么资源需要清理此处只是用来验证它的特性 class Date
{
public:Date(int year 1, int month 1, int day 1){_year year;_month month;_day day;}void Print(){cout _year - _month - _day endl;}~Date(){cout this endl;cout ~Date() endl;}
private:int _year;int _month;int _day;
};
void func()
{Date d2;
}
int main()
{func();Date d1;d1.Print();return 0;
} ⑤ 如果类中没有申请资源时析构函数可以不写 直接使用编译器生成的默认析构函数比如 Date类 有资源申请时一定要写 否则会造成资源泄漏比如Stack类。 如果我们写了一个栈忘记写析构函数会发生内存泄漏。虽然函数结束栈帧销毁但是在堆上额外开辟了一块空间没有释放。C语言中避免出现内存泄漏需要在函数结束前调用Destory函数来销毁但是这种方法在使用时极有可能忘记因而C中引入了析构函数。
class Stack
{
public:Stack(size_t capacity 4){_array (int*)malloc(sizeof(int) * capacity);if (NULL _array){perror(malloc申请空间失败!!!);return;}_capacity capacity;_size 0;}void Push(int data){// CheckCapacity();_array[_size] data;_size;}
private:int* _array;int _capacity;int _size;
};
int main()
{Stack Sreturn 0;
}
对以上代码加上析构函数结果如下 **先定义的先调用构造函数后定义的先调用析构函数 class Date
{
public:Date(int year){_year year;cout Date()- _year endl;}~Date(){cout ~Date()- _year endl;}
private:int _year 1;int _month 1;int _day 1;
};
Date d5(5);
static Date d6(6);
void func()
{Date d4(4);
}
int main()
{Date d1(1);static Date d2(2);Date d3(3);func();return 0;
} 分析上面代码猜测结果是什么 我们先分析一下各个对象是全局还是局部变量。d1、d2、d3、d4是局部变量d4是在函数 func() 内定义函数 func() 在main函数内调用所以d4的生命周期先结束。d2又被static修饰称为静态局部变量改变了它的存储位置使得它的生命周期变长直至程序结束生命周期才结束在销毁之前应先将main函数内的局部变量先销毁后定义先析构再销毁该静态局部变量。d5、d6是全局变量虽然d6被static修饰静态全局变量但它与全局变量的存储位置没有区别生命周期仍是整个程序的执行期间也是后定义的先析构。 所以调用析构函数的顺序是d4-d3-d1-d2-d6-d5。 结果如下 总结 调用析构函数的顺序局部对象后定义的先析构-静态局部对象-全局对象后定义的先析构 构造函数和析构函数的学习就到这了下篇我们将一起学习其他的默认成员函数谢谢观看