总述
构造函数是特殊的成员函数,只要创建类类型的新对象,都要执行构造函数。构造函数的工作是保证每个对象的数据成员具有合适的初始值。
构造函数的名字与类名相同,并且不能指定返回类型。构造函数也可以被重载。(注意:没有const构造函数一说。构造函数的工作是初始化对象,而不管对象是否为const。)
构造函数的初始化式
构造函数的格式如下:
//定义类的复制构造函数
Sales_item::Sales_item(const string &book): isbn(book), units_sold(0), revenue(0.0) {}
注:构造函数多了一个初始化列表(只在构造函数定义中出现,且初始化列表可以省略)
构造函数执行分两个阶段:1)初始化阶段; 2)普通的计算阶段(函数体{}中执行)。
对类类型数据成员,总是在初始化阶段调用构造函数初始化(隐示初始化时调用默认构造函数)。如果一个类没有默认构造函数则在初始化列表中必须显示对其进行初始化(调用其他构造函数即可)。如果类成员为const或引用类型成员时,必须在初始化列表中进行初始化(const和引用类型对象不能赋值,只能初始化)。类成员为其他内置类型时,使用初始化列表或者在函数体中赋值并无任何差别。
构造函数初始化列表顺序并非执行顺序。成员被初始化的次序是定义成员的次序。
默认构造函数相关
默认构造函数就是在没有显示提供初始化式时使用的构造函数。它由不带参数的构造函数,或者为所有形参提供默认实参的构造函数定义。
只有当一个类没有定义任何构造函数的时候编译器才会自动生成一个默认构造函数(合成的默认构造函数)。
类通常应该定义一个默认构造函数,该函数提供的初始值应该指出该对象是“空”的。
复制构造函数相关
复制构造函数只有单个形参,且该形参是对本类类型对象的引用(常用const修饰)。
类类型使用复制初始化=符号时,复制初始化总是调用复制构造函数创建一个临时对象,然后用复制构造函数将创建的临时对象复制到正在创建的对象。
只包含类类型成员或内置类型成员的类,无须显示定义复制构造函数。以下情形需要定义复制构造函数对复制对象时发生的事情加以控制:
1)有指针作为类成员或者有成员表示在构造函数中分配的其他资源; //????后面啥意思,能否有个例子
2)在创建新对象时需要做一些特殊工作的类。 //例子????
有的类对象不能复制(IO流等),此时必须显示声明其构造函数为private。
explicit关键字
explicit主要是用来修饰构造函数的,表示该构造函数是显示的。
每个含有一个参数的构造函数都定义了一个从该参数类型到类类型的隐式类型转换。
class myclass
{
public:
myclass(int num);
}
//由int隐式转换为myclass类型
myclass obj = 10;
最后一行相当于:
myclass temp(10);
myclass obj = temp;
如果使用explicit以下程序将报错
class myclass
{
public:
explicit myclass(int num);
}
myclass obj = 10;
通常,单形参的构造函数应该为explicit以避免隐式类类型转换。当转换有用时,用户可以显示的构造对象。