C++构造函数(一)

本篇是介绍C++的构造函数的第一篇(共二篇),属于读书笔记,对C++进行一个系统的复习。

构造函数的概念和作用

全局变量未初始化时为0,局部变量未初始化时的值却是无法预测的。这是因为,全局变量的初始化是再程序装载时便一次性完成的,自动地初始化为零并不会有额外的开销,因此编译器默认初始化为零。但是对局部变量并没有这样的操作,需要程序去完成初始化。

基本类型变量的初始化只需要在定义时赋值就可以了,但是对于对象的初始化,情况就要复杂一些。比如,有的对象需要在创建时就令某个指针指向一块内存空间,这就涉及到空间的分配;再比如,有的对象包含文件操作,在创建时就需要打开特定文件。举这两个例子是要说明,对象的初始化,不仅仅是简单赋值那么简单。因此构造函数(constructor)是必要的,它的存在就是为了完成对象的初始化工作。

构造函数名字和类名一样,没有返回值,可以重载。可以有多个构造函数,如果没有就自动生成一个默认的构造函数,但是它什么也不做。

默认构造函数

自动生成的构造函数是一个没有参数的构造函数。但凡自己已经写了一个构造函数,都不会自动生成无参的构造函数。不论是程序员自己写的无参构造函数还是自动生成的无参构造函数,只要是无参构造函数,就称为默认构造函数。那么,考虑下面一种情况:程序员只写了有参的构造函数,这种情况下就不存在默认构造函数。所以默认构造函数不一定存在,或者说无参的构造函数不一定存在。为什么要强调无参的构造函数不一定存在,有没有哪种构造函数一定是存在的呢?复制构造函数是一定存在的,在后文介绍。

对象在生成的时候一定会调用某个构造函数初始化,而对象一旦生成,就再也不会在其上调用构造函数。

构造函数是负责内存的分配吗?不是的,它只负责初始化。所以创建一个对象的过程是,先内存分配(在堆或栈上),之后在分配好的内存上调用构造函数。

构造函数在数组中的使用

像 int a[3] = { 0 ,1 ,2 }; 这样的语句就实现了数组的初始化。如何给一个对象数组初始化呢,可以使用类似的方法。

1 class CNum {
2 
3 int num;
4 public:
5 
6 CNum(){ num = 0;}
7 CNum(int a){ num = a;}
8 CNum(int a, int b){ num = a + b;}
9 }

可以这样调用:

1 CNum n1[3];                   //调用了三次无参构造函数,结果是{0,0,0}
2 CNum n2[3] = {0, 1, 2};           //调用了三次CNum(int a),结果是{0,1,2}
3 CNum n3[3] = {0, 1};             //调用了两次CNum(int a),和一次无参构造函数,结果是{0,1,0}
4 CNum n4[3] = {0, CNum(1,2), CNum(2,3)};  //调用了一次无参构造函数和两次CNum(int a, int b),结果是{0,3,5}

想在堆上生成数组可以这样:

1 CNum * ptrnum[3] = {new CNum(1,2), new CNum(2,3)};

这样生成的实际上是一个指针数组,前两个元素指向的对象使用了CNum(int a, int b)初始化,第三个元素没有初始化,是一个野指针(请避免这样做)。所以这一个语句实际上调用了两次构造函数。

 

原文地址:https://www.cnblogs.com/painterQ/p/7003814.html