1、构造函数的基本概念
每个类都分别定义了它的对象被初始化的方式,类通过一个或者几个特殊的成员函数来控制其对象初始化的过程,这些函数叫构造函数。
关于构造函数:
(1)作用:初始化对象的数据成员,只要对象创建就会被执行。
(2)返回值:无返回值
(3)参数:参数列表可以为空,函数体也可以为空
(4)构造函数重载:一个类可以包含多个构造函数,不同的构造函数之间必须在参数数量或者参数类型上有所区别。
(5)构造函数不能被声明为const的,同是当我们创建一个const对象时,只有当构造函数完成之后,对象才能真正取得常量属性。(不然,一开始就是常量怎么初始化呢?)
2、默认构造函数与合成的默认构造函数
当我们定义一个对象是,如果没有为这些对象提供初值,那么就会通过默认构造函数执行初始化,默认构造函数无需任何实参。
class Student
{
public:
Student() //显示定义一个默认构造函数
{
id=123;
}
Student(int ID):id(ID){}//有参数的构造函数
private:
int id;
};
Student xiaoming;//定义一个对象,没有提供初始值,执行默认构造函数,即id=123
如果我们的类没有显示定义构造函数,那么编译器就我们隐式的定义一个构造函数,这个构造函数称为合成的默认构造函数。由合成的默认构造函数按照一定规则初始化对象。
class Student
{
public:
//这一块没有显示定义构造函数
private:
int id;
};
Student xiaoming;//定义一个对象,没有提供初始值,执行合成的默认构造函数进行初始化
3、合成的默认构造函数初始化规则
对于大多数类来说,这个合成的默认构造函数将按照一下规则来初始化数据成员:
如果存在类内的初始值,用它来初始化成员 (情形1)-std=c++11
否则,执行默认初始化 (情形2)
struct Sales_item
{
std::string bookNo;
unsigned char units_sold=0;//类内存在初始值
double revenue=0;//类内存在初始值
};
Sales_item It;//执行合成的默认构造函数,类内初始值初始化(情形1)
//类内初始值初始化之后,It.units_sold=0, It.revenue=0
默认初始化规则:
………………非成员变量默认初始化规则(规则1)
如果变量是内置类型(int、double、char等)或者复合型(指针,数组),那么
定义于任何函数体外的内置型变量都会被初始化为0
定义于函数体内的内置型变量不被初始化
//内置类型初始化规则
#include <iostream>
using namespace std;
int i; //函数体外,初始化为0
double d; //函数体外,初始化为0
char *ptr; //函数体外,初始化为0
int arr[3]; //函数体外,初始化为0
int main() {
cout<<"i:"<<i<<" d:"<<d<<endl;
if(ptr==NULL)cout<<"ptr is NULL\n";
for(int k=0;k<3;k++)
cout<<arr[k]<<" ";
cout<<endl;
int jj;//********main函数体内定义,不被初始化,值是未确定的*****
return 0;
}
内置型变量变量如果没有初始化,容易引发运行故障,一定要尽量避免,即在定义内执行变量的时候,尽可能的将其初始化。
………………类成员变量默认初始化规则(规则2)
类成员变量默认初始化规则与非成员变量初始化规则类似
对象中的内置类型成员变量按规则1初始化
对象中的成员变量若是类类型,则该成员变量按默认构造函数初始化
#include <iostream>
using namespace std;
class Test
{
public:
int i;
double d;
char *ptr;
}
Test inTest;//函数体外定义的对象,那么
//对象中的内置型成员变量初始化为0,即inTest.i=0,inTest.d=0,inTest.ptr=NULL
int main() {
Test outTest;//函数体类定义的对象,那么内置型成员变量将不被初始化
return 0;
}
注意:
默认初始化的前提就是执行合成的默认构造函数,即类没有显示定义构造函数。否则,如果类定义了默认构造函数(即使默认构造函数啥也不做),也不会进行默认初始化。
补充说明:
变量声明与变量定义的关系
声明:使得名字为程序所知,一个文件想要使用别处定义的名字则必须要包含对那个名字的声明。
定义:负责创建与名字关联的实体。(分配内存空间)
想要声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示地初始化变量。
extern int i;//声明i,而非定义i
int j;//声明并定义j
extern double pi=3.1415;//定义
声明与定义的区别看起来微不足道,但是实际非常重要。如果多个文件想要使用同一个变量,那就必须将变量声明与定义分离。此时变量的定义必须出现在一个文件且只能出现在一个文件中,而其它用到该变量的文件必须对其进行声明,却绝对不能重复定义。
总之,变量能且只能被定义一次,但是可以有多次声明。
参考资料:
C++ Primer 中文版(第5版)
深度探索C++对象模型(侯捷译)